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.
1992 lines
59 KiB
1992 lines
59 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1997.
|
|
//
|
|
// File: S T E E L H E A D . C P P
|
|
//
|
|
// Contents: Implementation of Steelhead configuration object.
|
|
//
|
|
// Notes:
|
|
//
|
|
// Author: shaunco 15 Jun 1997
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "pch.h"
|
|
#pragma hdrstop
|
|
#include <mprerror.h>
|
|
#include <tdi.h> // must include for isnkrnl.h
|
|
#include <isnkrnl.h>
|
|
#include <rtinfo.h>
|
|
#include <rasman.h>
|
|
#include "ncreg.h"
|
|
#include "rasobj.h"
|
|
#include "ncsvc.h"
|
|
#include "netcfgp.h"
|
|
#include "router.h"
|
|
|
|
extern const WCHAR c_szBiNdis5[];
|
|
|
|
extern const WCHAR c_szInfId_MS_NdisWan[];
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Static data for adding router managers.
|
|
//
|
|
static const WCHAR c_szRtrMgrIp [] = L"Ip";
|
|
static const WCHAR c_szRtrMgrDllIp [] = L"%SystemRoot%\\System32\\iprtrmgr.dll";
|
|
static const WCHAR c_szRtrMgrIpx [] = L"Ipx";
|
|
static const WCHAR c_szRtrMgrDllIpx[] = L"%SystemRoot%\\System32\\ipxrtmgr.dll";
|
|
|
|
static const ROUTER_MANAGER_INFO c_rmiIp =
|
|
{
|
|
PID_IP,
|
|
0,
|
|
c_szRtrMgrIp,
|
|
c_szRtrMgrDllIp,
|
|
MakeIpInterfaceInfo,
|
|
MakeIpTransportInfo,
|
|
};
|
|
|
|
static const ROUTER_MANAGER_INFO c_rmiIpx =
|
|
{
|
|
PID_IPX,
|
|
ISN_FRAME_TYPE_AUTO,
|
|
c_szRtrMgrIpx,
|
|
c_szRtrMgrDllIpx ,
|
|
MakeIpxInterfaceInfo,
|
|
MakeIpxTransportInfo,
|
|
};
|
|
|
|
// These guids are defined in sdk\inc\ifguid.h
|
|
// We need the string versions.
|
|
//
|
|
// DEFINE_GUID(GUID_IpLoopbackInterface, 0xca6c0780, 0x7526, 0x11d2, 0xba, 0xf4, 0x00, 0x60, 0x08, 0x15, 0xa4, 0xbd);
|
|
// DEFINE_GUID(GUID_IpRasServerInterface, 0x6e06f030, 0x7526, 0x11d2, 0xba, 0xf4, 0x00, 0x60, 0x08, 0x15, 0xa4, 0xbd);
|
|
// DEFINE_GUID(GUID_IpxInternalInterface, 0xa571ba70, 0x7527, 0x11d2, 0xba, 0xf4, 0x00, 0x60, 0x08, 0x15, 0xa4, 0xbd);
|
|
|
|
//static const WCHAR c_szIpLoopbackInterface [] = L"ca6c0780-7526-11d2-00600815a4bd";
|
|
//static const WCHAR c_szIpRasServerInterface [] = L"6e06f030-7526-11d2-00600815a4bd";
|
|
//static const WCHAR c_szIpxInternalInterface [] = L"a571ba70-7527-11d2-00600815a4bd";
|
|
|
|
// For Ipx, the adapter name is the bind name.
|
|
// We need to create an interface per frame type.
|
|
// The interface name is the adapter name followed
|
|
// by these strings.
|
|
//
|
|
|
|
#pragma BEGIN_CONST_SECTION
|
|
static const MAP_SZ_DWORD c_mapFrameType [] =
|
|
{
|
|
L"/EthII", MISN_FRAME_TYPE_ETHERNET_II,
|
|
L"/802.3", MISN_FRAME_TYPE_802_3,
|
|
L"/802.2", MISN_FRAME_TYPE_802_2,
|
|
L"/SNAP", MISN_FRAME_TYPE_SNAP,
|
|
};
|
|
#pragma END_CONST_SECTION
|
|
|
|
NOTHROW
|
|
BOOL
|
|
FMapFrameTypeToString (
|
|
DWORD dwFrameType,
|
|
PCWSTR* ppszFrameType)
|
|
{
|
|
Assert (ppszFrameType);
|
|
|
|
for (int i = 0; i < celems (c_mapFrameType); i++)
|
|
{
|
|
if (dwFrameType == c_mapFrameType[i].dwValue)
|
|
{
|
|
*ppszFrameType = c_mapFrameType[i].pszValue;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
TraceTag (ttidRasCfg, "FMapFrameTypeToString: Unknown frame type %d!",
|
|
dwFrameType);
|
|
|
|
*ppszFrameType = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
NOTHROW
|
|
BOOL
|
|
FMapStringToFrameType (
|
|
PCWSTR pszFrameType,
|
|
DWORD* pdwFrameType)
|
|
{
|
|
Assert (pszFrameType);
|
|
Assert (pdwFrameType);
|
|
|
|
for (int i = 0; i < celems (c_mapFrameType); i++)
|
|
{
|
|
if (0 == lstrcmpW (pszFrameType, c_mapFrameType[i].pszValue))
|
|
{
|
|
*pdwFrameType = c_mapFrameType[i].dwValue;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
TraceTag (ttidRasCfg, "FMapStringToFrameType: Unknown frame type %S!",
|
|
pszFrameType);
|
|
|
|
*pdwFrameType = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HrShouldRouteOverAdapter
|
|
//
|
|
// Purpose: Indicate if we should router over the adapter or not.
|
|
//
|
|
// Arguments:
|
|
// pnccAdapter [in] Adapter to test.
|
|
// ppszBindName [out] Returned bindname if S_OK is returned.
|
|
//
|
|
// Returns: S_OK if we should router over the adapter, S_FALSE if not.
|
|
//
|
|
// Author: shaunco 27 Aug 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
|
|
HRESULT
|
|
HrShouldRouteOverAdapter (
|
|
INetCfgComponent* pnccAdapter,
|
|
PWSTR* ppszBindName)
|
|
{
|
|
Assert (pnccAdapter);
|
|
|
|
// Initialize the output parameter.
|
|
//
|
|
if (ppszBindName)
|
|
{
|
|
*ppszBindName = NULL;
|
|
}
|
|
|
|
// We should return S_OK if the adapter is physical or it supports
|
|
// a binding interface of ndis5. S_FALSE otherwise.
|
|
//
|
|
DWORD dwCharacter;
|
|
HRESULT hr = pnccAdapter->GetCharacteristics (&dwCharacter);
|
|
if (SUCCEEDED(hr) && !(dwCharacter & NCF_PHYSICAL))
|
|
{
|
|
INetCfgComponentBindings* pnccBindings;
|
|
hr = pnccAdapter->QueryInterface (
|
|
IID_INetCfgComponentBindings,
|
|
reinterpret_cast<VOID**>(&pnccBindings));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pnccBindings->SupportsBindingInterface (
|
|
NCF_UPPER, c_szBiNdis5);
|
|
|
|
ReleaseObj (pnccBindings);
|
|
}
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
// Only consider devices which are present.
|
|
//
|
|
// This check is made *after* the check for binding interface
|
|
// match above for two reasons. 1) It's much more expensive
|
|
// 2) for ndiswan devices which do not come online when they
|
|
// are installed (e.g. ndiswannbfout), GetDeviceStatus will
|
|
// fail. For this case we don't want to route over ndiswannbf
|
|
// anyhow so we should just return S_FALSE and not a failure.
|
|
//
|
|
DWORD dwStatus;
|
|
hr = pnccAdapter->GetDeviceStatus(&dwStatus);
|
|
if (SUCCEEDED(hr) && (CM_PROB_DEVICE_NOT_THERE == dwStatus))
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// SupportsBindingInterface may return S_OK or S_FALSE.
|
|
// We only want the bind name if we're going to return S_OK.
|
|
//
|
|
if ((S_OK == hr) && ppszBindName)
|
|
{
|
|
hr = pnccAdapter->GetBindName (ppszBindName);
|
|
}
|
|
|
|
TraceError ("HrShouldRouteOverAdapter", (S_FALSE == hr) ? S_OK : hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
#if (WINVER >= 0x0501)
|
|
|
|
BOOL
|
|
InitializeDialInRestriction();
|
|
|
|
#endif
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSteelhead::CSteelhead
|
|
//
|
|
// Purpose: Constructor
|
|
//
|
|
// Arguments:
|
|
// (none)
|
|
//
|
|
// Returns: Nothing.
|
|
//
|
|
// Author: shaunco 28 Jul 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
CSteelhead::CSteelhead () : CRasBindObject ()
|
|
{
|
|
m_hMprConfig = NULL;
|
|
m_hMprAdmin = NULL;
|
|
m_fRemoving = FALSE;
|
|
m_fUpdateRouterConfiguration = FALSE;
|
|
m_pnccMe = NULL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSteelhead::~CSteelhead
|
|
//
|
|
// Purpose: Destructor
|
|
//
|
|
// Arguments:
|
|
// (none)
|
|
//
|
|
// Returns: Nothing.
|
|
//
|
|
// Author: shaunco 28 Jul 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
CSteelhead::~CSteelhead ()
|
|
{
|
|
Assert (!m_hMprConfig);
|
|
Assert (!m_hMprAdmin);
|
|
|
|
ReleaseObj (m_pnccMe);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSteelhead::FAdapterExistsWithMatchingBindName
|
|
//
|
|
// Purpose:
|
|
//
|
|
// Arguments:
|
|
// pszAdapterName [in]
|
|
// ppnccAdapter [out]
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: shaunco 27 Aug 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
BOOL
|
|
CSteelhead::FAdapterExistsWithMatchingBindName (
|
|
PCWSTR pszAdapterName,
|
|
INetCfgComponent** ppnccAdapter)
|
|
{
|
|
Assert (pszAdapterName);
|
|
Assert (ppnccAdapter);
|
|
|
|
*ppnccAdapter = NULL;
|
|
|
|
BOOL fFound = FALSE;
|
|
|
|
// Enumerate physical adapters in the system.
|
|
//
|
|
HRESULT hr = S_OK;
|
|
CIterNetCfgComponent nccIter (m_pnc, &GUID_DEVCLASS_NET);
|
|
INetCfgComponent* pnccAdapter;
|
|
while (!fFound && S_OK == (hr = nccIter.HrNext (&pnccAdapter)))
|
|
{
|
|
// Only consider this adapter if we should router over it.
|
|
//
|
|
PWSTR pszBindName;
|
|
hr = HrShouldRouteOverAdapter (pnccAdapter, &pszBindName);
|
|
if (S_OK == hr)
|
|
{
|
|
if (0 == lstrcmpW (pszAdapterName, pszBindName))
|
|
{
|
|
fFound = TRUE;
|
|
|
|
*ppnccAdapter = pnccAdapter;
|
|
AddRefObj (pnccAdapter);
|
|
}
|
|
|
|
CoTaskMemFree (pszBindName);
|
|
}
|
|
|
|
ReleaseObj (pnccAdapter);
|
|
}
|
|
return fFound;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSteelhead::FIpxFrameTypeInUseOnAdapter
|
|
//
|
|
// Purpose:
|
|
//
|
|
// Arguments:
|
|
// dwFrameType []
|
|
// pszAdapterName []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: shaunco 27 Aug 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
BOOL
|
|
CSteelhead::FIpxFrameTypeInUseOnAdapter (
|
|
DWORD dwFrameType,
|
|
PCWSTR pszAdapterName)
|
|
{
|
|
// Assume its not in use. If PnccIpx() is NULL, it means IPX is not
|
|
// installed and the frame type is definately not in use on the adapter.
|
|
//
|
|
BOOL fRet = FALSE;
|
|
if (PnccIpx())
|
|
{
|
|
// Get the private interface off of the INetCfgComponent for IPX
|
|
// then we can query for a notify object interface
|
|
//
|
|
INetCfgComponentPrivate* pinccp;
|
|
HRESULT hr = PnccIpx()->QueryInterface(
|
|
IID_INetCfgComponentPrivate,
|
|
reinterpret_cast<VOID**>(&pinccp));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IIpxAdapterInfo* pIpxAdapterInfo;
|
|
hr = pinccp->QueryNotifyObject(
|
|
IID_IIpxAdapterInfo,
|
|
reinterpret_cast<VOID**>(&pIpxAdapterInfo));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Get the frametypes in use for this adapter.
|
|
//
|
|
DWORD adwFrameType [MISN_FRAME_TYPE_MAX + 1];
|
|
DWORD cdwFrameType;
|
|
hr = pIpxAdapterInfo->GetFrameTypesForAdapter (
|
|
pszAdapterName,
|
|
celems (adwFrameType),
|
|
adwFrameType,
|
|
&cdwFrameType);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
for (DWORD i = 0; i < cdwFrameType; i++)
|
|
{
|
|
if (dwFrameType == adwFrameType[i])
|
|
{
|
|
fRet = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
ReleaseObj (pIpxAdapterInfo);
|
|
}
|
|
|
|
ReleaseObj (pinccp);
|
|
}
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSteelhead::FIpxFrameTypeInUseOnAdapter
|
|
//
|
|
// Purpose:
|
|
//
|
|
// Arguments:
|
|
// pszFrameType []
|
|
// pszAdapterName []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: shaunco 27 Aug 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
BOOL
|
|
CSteelhead::FIpxFrameTypeInUseOnAdapter (
|
|
PCWSTR pszFrameType,
|
|
PCWSTR pszAdapterName)
|
|
{
|
|
// Assume its not in use. If PnccIpx() is NULL, it means IPX is not
|
|
// installed and the frame type is definately not in use on the adapter.
|
|
//
|
|
BOOL fRet = FALSE;
|
|
DWORD dwFrameType;
|
|
if (PnccIpx() && FMapStringToFrameType (pszFrameType, &dwFrameType))
|
|
{
|
|
fRet = FIpxFrameTypeInUseOnAdapter (dwFrameType, pszAdapterName);
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSteelhead::HrEnsureRouterInterfaceForAdapter
|
|
//
|
|
// Purpose: Ensures the router interface block for the specified
|
|
// interface (adapter) is present and that the specified router
|
|
// manger is configured for that interface.
|
|
//
|
|
// Arguments:
|
|
// dwIfType [in] Interface type
|
|
// dwPacketType [in] The packet type (IPX only, ignored othewise)
|
|
// pszAdapterName [in] The adapter name
|
|
// pszInterfaceName [in] The interface name
|
|
// rmi [in] The router manager
|
|
//
|
|
// Returns: S_OK or an error code.
|
|
//
|
|
// Author: shaunco 28 Jul 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT
|
|
CSteelhead::HrEnsureRouterInterfaceForAdapter (
|
|
ROUTER_INTERFACE_TYPE dwIfType,
|
|
DWORD dwPacketType,
|
|
PCWSTR pszAdapterName,
|
|
PCWSTR pszInterfaceName,
|
|
const ROUTER_MANAGER_INFO& rmi)
|
|
{
|
|
// Make sure the interface is created.
|
|
//
|
|
HANDLE hConfigInterface;
|
|
HANDLE hAdminInterface;
|
|
|
|
HRESULT hr = HrEnsureRouterInterface (
|
|
dwIfType,
|
|
pszInterfaceName,
|
|
&hConfigInterface,
|
|
&hAdminInterface);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Ensure the router manager is added to the interface.
|
|
//
|
|
hr = HrEnsureRouterInterfaceTransport (
|
|
pszAdapterName,
|
|
dwPacketType,
|
|
hConfigInterface,
|
|
hAdminInterface,
|
|
rmi);
|
|
}
|
|
TraceError ("CSteelhead::HrEnsureRouterInterfaceForAdapter", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSteelhead::HrEnsureIpxRouterInterfacesForAdapter
|
|
//
|
|
// Purpose:
|
|
//
|
|
// Arguments:
|
|
// pszAdapterName []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: shaunco 27 Aug 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT
|
|
CSteelhead::HrEnsureIpxRouterInterfacesForAdapter (
|
|
PCWSTR pszAdapterName)
|
|
{
|
|
AssertSz (PnccIpx(), "Why is this being called if IPX isn't installed?");
|
|
|
|
// Get the IIpxAdapterInfo interface from the IPX notify object.
|
|
// We'll use it to find out how adapters are configured under IPX.
|
|
//
|
|
IIpxAdapterInfo* pIpxAdapterInfo;
|
|
HRESULT hr = HrQueryNotifyObject (
|
|
PnccIpx(),
|
|
IID_IIpxAdapterInfo,
|
|
reinterpret_cast<VOID**>(&pIpxAdapterInfo));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Get the frametypes in use for this adapter.
|
|
//
|
|
DWORD adwFrameType [MISN_FRAME_TYPE_MAX + 1];
|
|
DWORD cdwFrameType;
|
|
hr = pIpxAdapterInfo->GetFrameTypesForAdapter (
|
|
pszAdapterName,
|
|
celems (adwFrameType),
|
|
adwFrameType,
|
|
&cdwFrameType);
|
|
if (SUCCEEDED(hr) && cdwFrameType)
|
|
{
|
|
// If more than one frame type is in use, or if there is only
|
|
// one and it isn't auto, then we'll be creating interfaces
|
|
// for those frame types explicitly.
|
|
//
|
|
if ((cdwFrameType > 1) ||
|
|
((1 == cdwFrameType) &&
|
|
(ISN_FRAME_TYPE_AUTO != adwFrameType[0])))
|
|
{
|
|
for (DWORD i = 0; SUCCEEDED(hr) && (i < cdwFrameType); i++)
|
|
{
|
|
PCWSTR pszFrameType;
|
|
if (FMapFrameTypeToString (adwFrameType[i], &pszFrameType))
|
|
{
|
|
// Make the interface name by catenating the
|
|
// adapter (bind) name with the frame type.
|
|
//
|
|
WCHAR szInterfaceName [512];
|
|
lstrcpyW (szInterfaceName, pszAdapterName);
|
|
lstrcatW (szInterfaceName, pszFrameType);
|
|
|
|
hr = HrEnsureRouterInterfaceForAdapter (
|
|
ROUTER_IF_TYPE_DEDICATED,
|
|
adwFrameType[i],
|
|
pszAdapterName,
|
|
szInterfaceName,
|
|
c_rmiIpx);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Otherwise, we'll create the interface for the auto frame
|
|
// type case.
|
|
//
|
|
else
|
|
{
|
|
#ifdef DBG
|
|
AssertSz (1 == cdwFrameType,
|
|
"IPX should report at least one frame type. "
|
|
"You may continue without a problem.");
|
|
if (1 == cdwFrameType)
|
|
{
|
|
AssertSz (ISN_FRAME_TYPE_AUTO == adwFrameType[0],
|
|
"Frame type should be auto here. "
|
|
"You may continue without a problem.");
|
|
}
|
|
#endif
|
|
hr = HrEnsureRouterInterfaceForAdapter (
|
|
ROUTER_IF_TYPE_DEDICATED,
|
|
ISN_FRAME_TYPE_AUTO,
|
|
pszAdapterName,
|
|
pszAdapterName,
|
|
c_rmiIpx);
|
|
}
|
|
}
|
|
|
|
ReleaseObj (pIpxAdapterInfo);
|
|
}
|
|
|
|
TraceError ("CSteelhead::HrEnsureIpxRouterInterfacesForAdapter", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSteelhead::HrEnsureRouterInterface
|
|
//
|
|
// Purpose: Ensures the specified router interface is present and
|
|
// returns a handle to it.
|
|
//
|
|
// Arguments:
|
|
// pszInterfaceName [in] The interface (adapter) name
|
|
// phConfigInterface [out] Returned handle to the interface
|
|
//
|
|
// Returns: S_OK or an error code.
|
|
//
|
|
// Author: shaunco 28 Jul 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT
|
|
CSteelhead::HrEnsureRouterInterface (
|
|
ROUTER_INTERFACE_TYPE dwIfType,
|
|
PCWSTR pszInterfaceName,
|
|
HANDLE* phConfigInterface,
|
|
HANDLE* phAdminInterface)
|
|
{
|
|
Assert (pszInterfaceName);
|
|
Assert (phConfigInterface);
|
|
Assert (phAdminInterface);
|
|
|
|
// Initialize the output parameters.
|
|
//
|
|
*phConfigInterface = NULL;
|
|
*phAdminInterface = NULL;
|
|
|
|
HRESULT hrConfig;
|
|
HRESULT hrAdmin;
|
|
|
|
hrConfig = HrMprConfigInterfaceGetHandle (m_hMprConfig,
|
|
const_cast<PWSTR>(pszInterfaceName),
|
|
phConfigInterface);
|
|
|
|
hrAdmin = HrMprAdminInterfaceGetHandle (m_hMprAdmin,
|
|
const_cast<PWSTR>(pszInterfaceName),
|
|
phAdminInterface, FALSE);
|
|
|
|
if ((HRESULT_FROM_WIN32 (ERROR_NO_SUCH_INTERFACE ) == hrConfig) ||
|
|
(HRESULT_FROM_WIN32 (ERROR_NO_SUCH_INTERFACE ) == hrAdmin))
|
|
{
|
|
// It's not installed, so we'll create it.
|
|
//
|
|
|
|
MPR_INTERFACE_0 ri0;
|
|
ZeroMemory (&ri0, sizeof(ri0));
|
|
ri0.hInterface = INVALID_HANDLE_VALUE;
|
|
ri0.fEnabled = TRUE; // thanks gibbs
|
|
ri0.dwIfType = dwIfType;
|
|
|
|
// Copy the interface name into the buffer.
|
|
//
|
|
AssertSz (lstrlenW (pszInterfaceName) < celems (ri0.wszInterfaceName),
|
|
"Bindname too big for MPR_INTERFACE_0 buffer.");
|
|
lstrcpyW (ri0.wszInterfaceName, pszInterfaceName);
|
|
|
|
// Create the interface.
|
|
//
|
|
if (HRESULT_FROM_WIN32 (ERROR_NO_SUCH_INTERFACE) == hrConfig)
|
|
{
|
|
hrConfig = HrMprConfigInterfaceCreate (
|
|
m_hMprConfig, 0, (LPBYTE)&ri0, phConfigInterface);
|
|
|
|
TraceTag (ttidRasCfg, "MprConfigInterfaceCreate for %S",
|
|
pszInterfaceName);
|
|
}
|
|
|
|
if (HRESULT_FROM_WIN32 (ERROR_NO_SUCH_INTERFACE) == hrAdmin)
|
|
{
|
|
hrAdmin = HrMprAdminInterfaceCreate (
|
|
m_hMprAdmin, 0, (LPBYTE)&ri0, phAdminInterface);
|
|
|
|
TraceTag (ttidRasCfg, "MprAdminInterfaceCreate for %S",
|
|
pszInterfaceName);
|
|
}
|
|
}
|
|
|
|
TraceError ("CSteelhead::HrEnsureRouterInterface", hrConfig);
|
|
return hrConfig;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSteelhead::HrEnsureRouterInterfaceTransport
|
|
//
|
|
// Purpose: Ensures the specified router manager is configured over
|
|
// the specified interface.
|
|
//
|
|
// Arguments:
|
|
// pszAdapterName [in] The adapter name
|
|
// dwPacketType [in] The packet type (IPX only, ignored otherwise)
|
|
// hInterface [in] Handle to the interface
|
|
// rmi [in] The router manager
|
|
//
|
|
// Returns: S_OK or an error code.
|
|
//
|
|
// Author: shaunco 28 Jul 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT
|
|
CSteelhead::HrEnsureRouterInterfaceTransport (
|
|
PCWSTR pszAdapterName,
|
|
DWORD dwPacketType,
|
|
HANDLE hConfigInterface,
|
|
HANDLE hAdminInterface,
|
|
const ROUTER_MANAGER_INFO& rmi)
|
|
{
|
|
Assert (hConfigInterface);
|
|
// hAdminInterface may be NULL if the router is not running.
|
|
|
|
HRESULT hrConfig;
|
|
|
|
// See if the router manager is present on the interface.
|
|
//
|
|
HANDLE hIfTransport;
|
|
|
|
hrConfig = HrMprConfigInterfaceTransportGetHandle (
|
|
m_hMprConfig, hConfigInterface,
|
|
rmi.dwTransportId, &hIfTransport);
|
|
|
|
if (FAILED(hrConfig))
|
|
{
|
|
// Ensure the router manager is present.
|
|
//
|
|
hrConfig = HrEnsureRouterManager (rmi);
|
|
|
|
if (SUCCEEDED(hrConfig))
|
|
{
|
|
// Create the interface info and add the router manager to
|
|
// the interface.
|
|
//
|
|
PRTR_INFO_BLOCK_HEADER pibh;
|
|
|
|
Assert (rmi.pfnMakeInterfaceInfo);
|
|
rmi.pfnMakeInterfaceInfo (pszAdapterName,
|
|
dwPacketType,
|
|
(LPBYTE*)&pibh);
|
|
|
|
hrConfig = HrMprConfigInterfaceTransportAdd (
|
|
m_hMprConfig,
|
|
hConfigInterface,
|
|
rmi.dwTransportId,
|
|
const_cast<PWSTR>(rmi.pszwTransportName),
|
|
(LPBYTE)pibh,
|
|
pibh->Size,
|
|
&hIfTransport);
|
|
|
|
TraceTag (ttidRasCfg, "MprConfigInterfaceTransportAdd for "
|
|
"%S on %S",
|
|
rmi.pszwTransportName,
|
|
pszAdapterName);
|
|
|
|
if (SUCCEEDED(hrConfig) && hAdminInterface)
|
|
{
|
|
Assert (m_hMprAdmin);
|
|
(VOID) HrMprAdminInterfaceTransportAdd (
|
|
m_hMprAdmin,
|
|
hAdminInterface,
|
|
rmi.dwTransportId,
|
|
(LPBYTE)pibh,
|
|
pibh->Size);
|
|
|
|
TraceTag (ttidRasCfg, "MprAdminInterfaceTransportAdd for "
|
|
"%S on %S",
|
|
rmi.pszwTransportName,
|
|
pszAdapterName);
|
|
}
|
|
|
|
MemFree (pibh);
|
|
}
|
|
}
|
|
TraceError ("CSteelhead::HrEnsureRouterInterfaceTransport", hrConfig);
|
|
return hrConfig;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSteelhead::HrEnsureRouterManager
|
|
//
|
|
// Purpose: Ensures that the specified router manager is installed.
|
|
//
|
|
// Arguments:
|
|
// rmi [in] The router manager.
|
|
//
|
|
// Returns: S_OK or an error code.
|
|
//
|
|
// Author: shaunco 28 Jul 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT
|
|
CSteelhead::HrEnsureRouterManager (
|
|
const ROUTER_MANAGER_INFO& rmi)
|
|
{
|
|
PRTR_INFO_BLOCK_HEADER pibhGlobal;
|
|
BOOL fCreate = FALSE;
|
|
|
|
// See if the router manager is installed.
|
|
//
|
|
HANDLE hTransport;
|
|
HRESULT hr = HrMprConfigTransportGetHandle (m_hMprConfig,
|
|
rmi.dwTransportId,
|
|
&hTransport);
|
|
if (HRESULT_FROM_WIN32 (ERROR_UNKNOWN_PROTOCOL_ID) == hr)
|
|
{
|
|
// It's not installed, we'll create it.
|
|
//
|
|
fCreate = TRUE;
|
|
}
|
|
else if (SUCCEEDED(hr))
|
|
{
|
|
// Its installed, see if its transport info is available.
|
|
//
|
|
DWORD dwSize;
|
|
hr = HrMprConfigTransportGetInfo (m_hMprConfig, hTransport,
|
|
(LPBYTE*)&pibhGlobal, &dwSize,
|
|
NULL, NULL, NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!pibhGlobal)
|
|
{
|
|
// Global info is missing, we'll create it.
|
|
//
|
|
fCreate = TRUE;
|
|
}
|
|
else
|
|
{
|
|
MprConfigBufferFree (pibhGlobal);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fCreate)
|
|
{
|
|
// Install the router manager.
|
|
//
|
|
Assert (rmi.pfnMakeTransportInfo);
|
|
PRTR_INFO_BLOCK_HEADER pibhClient;
|
|
rmi.pfnMakeTransportInfo ((LPBYTE*)&pibhGlobal,
|
|
(LPBYTE*)&pibhClient);
|
|
|
|
hr = HrMprConfigTransportCreate (
|
|
m_hMprConfig,
|
|
rmi.dwTransportId,
|
|
const_cast<PWSTR>(rmi.pszwTransportName),
|
|
(LPBYTE)pibhGlobal, (pibhGlobal) ? pibhGlobal->Size : 0,
|
|
(LPBYTE)pibhClient, (pibhClient) ? pibhClient->Size : 0,
|
|
const_cast<PWSTR>(rmi.pszwDllPath),
|
|
&hTransport);
|
|
|
|
(VOID) HrMprAdminTransportCreate (
|
|
m_hMprAdmin,
|
|
rmi.dwTransportId,
|
|
const_cast<PWSTR>(rmi.pszwTransportName),
|
|
(LPBYTE)pibhGlobal, (pibhGlobal) ? pibhGlobal->Size : 0,
|
|
(LPBYTE)pibhClient, (pibhClient) ? pibhClient->Size : 0,
|
|
const_cast<PWSTR>(rmi.pszwDllPath));
|
|
|
|
MemFree (pibhGlobal);
|
|
MemFree (pibhClient);
|
|
}
|
|
TraceError ("CSteelhead::HrEnsureRouterManager", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSteelhead::HrEnsureRouterManagerDeleted
|
|
//
|
|
// Purpose: Ensures that the specified router manager is not installed.
|
|
//
|
|
// Arguments:
|
|
// rmi [in] The router manager.
|
|
//
|
|
// Returns: S_OK or an error code.
|
|
//
|
|
// Author: shaunco 6 Sep 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT CSteelhead::HrEnsureRouterManagerDeleted (
|
|
const ROUTER_MANAGER_INFO& rmi)
|
|
{
|
|
// See if the router manager is installed.
|
|
//
|
|
HANDLE hTransport;
|
|
HRESULT hr = HrMprConfigTransportGetHandle (m_hMprConfig,
|
|
rmi.dwTransportId,
|
|
&hTransport);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// It is installed, so we need to delete it.
|
|
//
|
|
(VOID) HrMprConfigTransportDelete (m_hMprConfig, hTransport);
|
|
}
|
|
TraceError ("CSteelhead::HrEnsureRouterManagerDeleted",
|
|
(HRESULT_FROM_WIN32 (ERROR_UNKNOWN_PROTOCOL_ID) == hr)
|
|
? S_OK : hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSteelhead::HrPassToAddInterfaces
|
|
//
|
|
// Purpose:
|
|
//
|
|
// Arguments:
|
|
// (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: shaunco 27 Aug 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT
|
|
CSteelhead::HrPassToAddInterfaces ()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Enumerate physical adapters in the system.
|
|
//
|
|
CIterNetCfgComponent nccIter(m_pnc, &GUID_DEVCLASS_NET);
|
|
INetCfgComponent* pnccAdapter;
|
|
while (S_OK == (hr = nccIter.HrNext(&pnccAdapter)))
|
|
{
|
|
// Only consider this adapter if we should router over it.
|
|
//
|
|
PWSTR pszBindName;
|
|
hr = HrShouldRouteOverAdapter (pnccAdapter, &pszBindName);
|
|
if (S_OK == hr)
|
|
{
|
|
INetCfgComponentBindings* pnccBindingsIp = NULL;
|
|
INetCfgComponentBindings* pnccBindingsIpx = NULL;
|
|
|
|
// If Ip is bound to the adapter, create and interface
|
|
// for it.
|
|
//
|
|
if (PnccIp())
|
|
{
|
|
hr = PnccIp()->QueryInterface (IID_INetCfgComponentBindings,
|
|
reinterpret_cast<VOID**>(&pnccBindingsIp) );
|
|
}
|
|
if (PnccIp() && SUCCEEDED(hr) &&
|
|
(S_OK == (hr = pnccBindingsIp->IsBoundTo (pnccAdapter))))
|
|
{
|
|
// Interface name is the same as the adapter name
|
|
// is the same as the bind name.
|
|
//
|
|
hr = HrEnsureRouterInterfaceForAdapter (
|
|
ROUTER_IF_TYPE_DEDICATED,
|
|
0,
|
|
pszBindName,
|
|
pszBindName,
|
|
c_rmiIp);
|
|
|
|
}
|
|
ReleaseObj (pnccBindingsIp);
|
|
|
|
// If Ipx is bound to the adapter, create the interface(s)
|
|
// for it.
|
|
if (PnccIpx())
|
|
{
|
|
hr = PnccIpx()->QueryInterface (IID_INetCfgComponentBindings,
|
|
reinterpret_cast<VOID**>(&pnccBindingsIpx));
|
|
}
|
|
if (PnccIpx() &&
|
|
(S_OK == (hr = pnccBindingsIpx->IsBoundTo( pnccAdapter )) ))
|
|
{
|
|
#if (WINVER < 0x0501)
|
|
hr = HrEnsureIpxRouterInterfacesForAdapter (pszBindName);
|
|
#endif
|
|
}
|
|
ReleaseObj (pnccBindingsIpx);
|
|
|
|
CoTaskMemFree (pszBindName);
|
|
}
|
|
|
|
ReleaseObj (pnccAdapter);
|
|
}
|
|
// Normalize the HRESULT. (i.e. don't return S_FALSE)
|
|
if (S_FALSE == hr)
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
|
|
TraceError ("CSteelhead::HrPassToAddInterfaces", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSteelhead::HrPassToRemoveInterfaces
|
|
//
|
|
// Purpose:
|
|
//
|
|
// Arguments:
|
|
// (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: shaunco 27 Aug 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT
|
|
CSteelhead::HrPassToRemoveInterfaces (
|
|
BOOL fFromRunningRouter)
|
|
{
|
|
// Enumerate all of the installed router interfaces.
|
|
//
|
|
MPR_INTERFACE_0* ari0;
|
|
DWORD dwEntriesRead;
|
|
DWORD dwTotalEntries;
|
|
HRESULT hr;
|
|
|
|
if (fFromRunningRouter)
|
|
{
|
|
Assert (m_hMprAdmin);
|
|
hr = HrMprAdminInterfaceEnum (m_hMprAdmin, 0,
|
|
reinterpret_cast<LPBYTE*>(&ari0),
|
|
-1, &dwEntriesRead, &dwTotalEntries, NULL);
|
|
}
|
|
else
|
|
{
|
|
hr = HrMprConfigInterfaceEnum (m_hMprConfig, 0,
|
|
reinterpret_cast<LPBYTE*>(&ari0),
|
|
-1, &dwEntriesRead, &dwTotalEntries, NULL);
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// By passing -1, we want everything, so we should get everything.
|
|
Assert (dwEntriesRead == dwTotalEntries);
|
|
|
|
// Iterate all of the interfaces.
|
|
//
|
|
for (MPR_INTERFACE_0* pri0 = ari0; dwEntriesRead--; pri0++)
|
|
{
|
|
BOOL fDeleteInterface = FALSE;
|
|
PCWSTR pszInternalAdapter = SzLoadIds (IDS_RAS_INTERNAL_ADAPTER);
|
|
|
|
// If its the internal interface and IP and IPX are no longer
|
|
// installed delete the interface.
|
|
//
|
|
if ((ROUTER_IF_TYPE_INTERNAL == pri0->dwIfType) &&
|
|
!PnccIpx() && !PnccIp() &&
|
|
(0 == lstrcmpW (pri0->wszInterfaceName, pszInternalAdapter)))
|
|
{
|
|
fDeleteInterface = TRUE;
|
|
}
|
|
else if (ROUTER_IF_TYPE_DEDICATED != pri0->dwIfType)
|
|
{
|
|
// Skip non-dedicated interfaces.
|
|
//
|
|
continue;
|
|
}
|
|
|
|
BOOL fSpecialIpxInterface = FALSE;
|
|
INetCfgComponent* pnccAdapter = NULL;
|
|
|
|
// Get the name of the interface and look for a '/' separator.
|
|
// If present, it means this is a special IPX interface where
|
|
// the first substring is the adapter name, and the second
|
|
// substring is the frame type.
|
|
//
|
|
WCHAR* pchwSep = wcschr (pri0->wszInterfaceName, L'/');
|
|
if (!fDeleteInterface && pchwSep)
|
|
{
|
|
fSpecialIpxInterface = TRUE;
|
|
|
|
// Point to the frame type string.
|
|
//
|
|
PCWSTR pszFrameType = pchwSep;
|
|
|
|
// Copy the adapter name into its own buffer.
|
|
//
|
|
WCHAR szAdapterName [MAX_INTERFACE_NAME_LEN+1];
|
|
lstrcpynW (szAdapterName, pri0->wszInterfaceName,
|
|
(int)(pchwSep - pri0->wszInterfaceName + 1));
|
|
|
|
// If the frame type is not in use for the adapter, we need
|
|
// to delete this interface. This condition happens when
|
|
// IPX configuration is changed and the frame type is removed
|
|
// from the adapter.
|
|
//
|
|
if (!FIpxFrameTypeInUseOnAdapter (pszFrameType,
|
|
szAdapterName))
|
|
{
|
|
fDeleteInterface = TRUE;
|
|
TraceTag (ttidRasCfg, "%S no longer in use on %S. "
|
|
"Deleting the router interface.",
|
|
pszFrameType, szAdapterName);
|
|
}
|
|
}
|
|
|
|
// It's not a special interface, so just make sure an adapter
|
|
// exists with a matching bind name. If not, we will delete
|
|
// the interface.
|
|
//
|
|
else if (!fDeleteInterface)
|
|
{
|
|
if (!FAdapterExistsWithMatchingBindName (
|
|
pri0->wszInterfaceName,
|
|
&pnccAdapter))
|
|
{
|
|
fDeleteInterface = TRUE;
|
|
TraceTag (ttidRasCfg, "%S no longer present. "
|
|
"Deleting the router interface.",
|
|
pri0->wszInterfaceName);
|
|
}
|
|
}
|
|
|
|
// Delete the interface if we need to.
|
|
//
|
|
if (fDeleteInterface)
|
|
{
|
|
if (fFromRunningRouter)
|
|
{
|
|
MprAdminInterfaceDelete (m_hMprAdmin, pri0->hInterface);
|
|
}
|
|
else
|
|
{
|
|
MprConfigInterfaceDelete (m_hMprConfig, pri0->hInterface);
|
|
}
|
|
}
|
|
|
|
// If we don't need to delete the entire interface, check
|
|
// for transports on the interface that we may need to delete.
|
|
// Don't do this for the running router because there is
|
|
// no MprAdminInterfaceTransportEnum API.
|
|
//
|
|
else if (!fFromRunningRouter)
|
|
{
|
|
// If its not an IPX special interface, the adapter
|
|
// is the interface name. If it is an IPX special
|
|
// interface, then we would have already remove the entire
|
|
// interface above if it were invalid.
|
|
//
|
|
(VOID) HrPassToRemoveInterfaceTransports (
|
|
pri0,
|
|
(!fSpecialIpxInterface) ? pri0->wszInterfaceName
|
|
: NULL,
|
|
pnccAdapter);
|
|
}
|
|
|
|
ReleaseObj (pnccAdapter);
|
|
}
|
|
|
|
MprConfigBufferFree (ari0);
|
|
}
|
|
else if ((HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr) ||
|
|
(HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) == hr) ||
|
|
(HRESULT_FROM_WIN32(RPC_S_UNKNOWN_IF) == hr))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
TraceError ("CSteelhead::HrPassToRemoveInterfaces", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSteelhead::HrPassToRemoveInterfaceTransports
|
|
//
|
|
// Purpose:
|
|
//
|
|
// Arguments:
|
|
// hInterface []
|
|
// pszAdapterName []
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: shaunco 27 Aug 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT
|
|
CSteelhead::HrPassToRemoveInterfaceTransports (
|
|
MPR_INTERFACE_0* pri0,
|
|
PCWSTR pszAdapterName,
|
|
INetCfgComponent* pnccAdapter)
|
|
{
|
|
Assert (FImplies(pnccAdapter, pszAdapterName));
|
|
|
|
// Enumerate all of the transports active on the router interface.
|
|
//
|
|
MPR_IFTRANSPORT_0* arit0;
|
|
DWORD dwEntriesRead;
|
|
DWORD dwTotalEntries;
|
|
HRESULT hr = HrMprConfigInterfaceTransportEnum (m_hMprConfig,
|
|
pri0->hInterface, 0,
|
|
reinterpret_cast<LPBYTE*>(&arit0),
|
|
-1, &dwEntriesRead, &dwTotalEntries, NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// By passing -1, we want everything, so we should get everything.
|
|
Assert (dwEntriesRead == dwTotalEntries);
|
|
|
|
INetCfgComponentBindings* pnccBindingsIpx = NULL;
|
|
INetCfgComponentBindings* pnccBindingsIp = NULL;
|
|
|
|
if (PnccIp())
|
|
{
|
|
hr = PnccIp()->QueryInterface (IID_INetCfgComponentBindings,
|
|
reinterpret_cast<VOID**>(&pnccBindingsIp));
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (PnccIpx())
|
|
{
|
|
hr = PnccIpx()->QueryInterface (IID_INetCfgComponentBindings,
|
|
reinterpret_cast<VOID**>(&pnccBindingsIpx));
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Iterate all of the transports.
|
|
//
|
|
for (MPR_IFTRANSPORT_0* prit0 = arit0; dwEntriesRead--; prit0++)
|
|
{
|
|
BOOL fDeleteInterfaceTransport = FALSE;
|
|
|
|
if (prit0->dwTransportId == c_rmiIp.dwTransportId)
|
|
{
|
|
if (!PnccIp())
|
|
{
|
|
fDeleteInterfaceTransport = TRUE;
|
|
TraceTag (ttidRasCfg, "TCP/IP no longer present. "
|
|
"Deleting this transport from interface %S.",
|
|
pri0->wszInterfaceName);
|
|
}
|
|
else if (pnccAdapter &&
|
|
(S_OK != (hr = pnccBindingsIp->IsBoundTo (pnccAdapter))))
|
|
{
|
|
fDeleteInterfaceTransport = TRUE;
|
|
TraceTag (ttidRasCfg, "TCP/IP no longer bound. "
|
|
"Deleting this transport from interface %S.",
|
|
pri0->wszInterfaceName);
|
|
}
|
|
}
|
|
else if (prit0->dwTransportId == c_rmiIpx.dwTransportId)
|
|
{
|
|
if (!PnccIpx())
|
|
{
|
|
fDeleteInterfaceTransport = TRUE;
|
|
TraceTag (ttidRasCfg, "IPX no longer present. "
|
|
"Deleting this transport from interface %S.",
|
|
pri0->wszInterfaceName);
|
|
}
|
|
else if (pnccAdapter &&
|
|
(S_OK != (hr = pnccBindingsIpx->IsBoundTo (pnccAdapter))))
|
|
{
|
|
fDeleteInterfaceTransport = TRUE;
|
|
TraceTag (ttidRasCfg, "IPX no longer bound. "
|
|
"Deleting this transport from interface %S.",
|
|
pri0->wszInterfaceName);
|
|
}
|
|
else if (pszAdapterName)
|
|
{
|
|
Assert (PnccIpx());
|
|
|
|
// if frame type is not auto on this adapter, delete
|
|
// the transport
|
|
if (!FIpxFrameTypeInUseOnAdapter (ISN_FRAME_TYPE_AUTO,
|
|
pszAdapterName))
|
|
{
|
|
fDeleteInterfaceTransport = TRUE;
|
|
TraceTag (ttidRasCfg, "IPX Auto frame type no longer "
|
|
"in use on %S. "
|
|
"Deleting this transport from interface %S.",
|
|
pszAdapterName, pri0->wszInterfaceName);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fDeleteInterfaceTransport)
|
|
{
|
|
MprConfigInterfaceTransportRemove (
|
|
m_hMprConfig,
|
|
pri0->hInterface,
|
|
prit0->hIfTransport);
|
|
}
|
|
|
|
}
|
|
MprConfigBufferFree (arit0);
|
|
|
|
ReleaseObj (pnccBindingsIpx);
|
|
}
|
|
|
|
ReleaseObj (pnccBindingsIp);
|
|
}
|
|
}
|
|
else if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr)
|
|
{
|
|
// If there are no transports for this interface, that's okay.
|
|
//
|
|
hr = S_OK;
|
|
}
|
|
|
|
TraceError ("CSteelhead::HrPassToRemoveInterfaceTransports", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSteelhead::HrUpdateRouterConfiguration
|
|
//
|
|
// Purpose: Updates the router configuration by ensuring router managers
|
|
// are installed for the protocols present on the system (IP and
|
|
// IPX). Further, router interfaces are created for each
|
|
// physical netcard present on the system.
|
|
//
|
|
// Arguments:
|
|
// (none)
|
|
//
|
|
// Returns: S_OK or an error code.
|
|
//
|
|
// Author: shaunco 28 Jul 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT
|
|
CSteelhead::HrUpdateRouterConfiguration ()
|
|
{
|
|
HKEY hKey;
|
|
|
|
Assert (!m_hMprConfig);
|
|
|
|
HRESULT hr = HrMprConfigServerConnect (NULL, &m_hMprConfig);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
PCWSTR pszInternalAdapter = SzLoadIds (IDS_RAS_INTERNAL_ADAPTER);
|
|
PCWSTR pszLoopbackAdapter = SzLoadIds (IDS_RAS_LOOPBACK_ADAPTER);
|
|
|
|
// Connect to the running router if able.
|
|
// (m_hMprAdmin will be non-NULL if we do.)
|
|
//
|
|
Assert (!m_hMprAdmin);
|
|
(VOID) HrMprAdminServerConnect (NULL, &m_hMprAdmin);
|
|
|
|
// Ensure router managers are installed for the protocols
|
|
// we know about. Good to do this in case no physical adapters.
|
|
// are found below. We actually do this by ensuring the internal
|
|
// interface exists. This will implicitly ensure the router
|
|
// manger is created.
|
|
//
|
|
if (PnccIp())
|
|
{
|
|
(VOID) HrEnsureRouterInterfaceForAdapter (
|
|
ROUTER_IF_TYPE_LOOPBACK,
|
|
c_rmiIp.dwPacketType,
|
|
pszLoopbackAdapter,
|
|
pszLoopbackAdapter,
|
|
c_rmiIp);
|
|
|
|
(VOID) HrEnsureRouterInterfaceForAdapter (
|
|
ROUTER_IF_TYPE_INTERNAL,
|
|
c_rmiIp.dwPacketType,
|
|
pszInternalAdapter,
|
|
pszInternalAdapter,
|
|
c_rmiIp);
|
|
}
|
|
else
|
|
{
|
|
(VOID) HrEnsureRouterManagerDeleted (c_rmiIp);
|
|
}
|
|
|
|
if (PnccIpx())
|
|
{
|
|
(VOID) HrEnsureRouterInterfaceForAdapter (
|
|
ROUTER_IF_TYPE_INTERNAL,
|
|
c_rmiIpx.dwPacketType,
|
|
pszInternalAdapter,
|
|
pszInternalAdapter,
|
|
c_rmiIpx);
|
|
}
|
|
else
|
|
{
|
|
(VOID) HrEnsureRouterManagerDeleted (c_rmiIpx);
|
|
}
|
|
|
|
(VOID) HrPassToAddInterfaces ();
|
|
|
|
(VOID) HrPassToRemoveInterfaces (FALSE);
|
|
|
|
// If we have a connection to the running router, make a pass
|
|
// to remove interfaces from it.
|
|
//
|
|
if (m_hMprAdmin)
|
|
{
|
|
(VOID) HrPassToRemoveInterfaces (TRUE);
|
|
#if (WINVER >= 0x0501)
|
|
(VOID) HrRemoveIPXRouterConfiguration(TRUE);
|
|
#endif
|
|
MprAdminServerDisconnect (m_hMprAdmin);
|
|
m_hMprAdmin = NULL;
|
|
}
|
|
|
|
#if (WINVER >= 0x0501)
|
|
(VOID) HrRemoveIPXRouterConfiguration(FALSE);
|
|
|
|
//
|
|
// Remove IPX router Manager configuration
|
|
//
|
|
|
|
(VOID) HrEnsureRouterManagerDeleted(c_rmiIpx);
|
|
|
|
//
|
|
// Remove IPX keys under HKLM\Software\Microsoft\Router\CurrentVersion
|
|
//
|
|
|
|
hr = HrRegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
L"Software\\Microsoft\\Router\\CurrentVersion\\RouterManagers",
|
|
KEY_ALL_ACCESS,
|
|
&hKey
|
|
);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
(VOID) SHDeleteKey(hKey, L"Ipx");
|
|
RegCloseKey(hKey);
|
|
hKey = NULL;
|
|
}
|
|
|
|
//
|
|
// Remove IPX keys under HKLM\Software\Microsoft\IPXMibAgent
|
|
//
|
|
|
|
hr = HrRegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
L"Software\\Microsoft",
|
|
KEY_ALL_ACCESS,
|
|
&hKey
|
|
);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
(VOID) SHDeleteKey(hKey, L"IPXMibAgent");
|
|
RegCloseKey(hKey);
|
|
hKey = NULL;
|
|
}
|
|
|
|
//
|
|
// Remove keys for NWLNKFWD and NWLNKFLT
|
|
//
|
|
|
|
hr = HrRegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
L"System\\CurrentControlSet\\Services",
|
|
KEY_ALL_ACCESS,
|
|
&hKey
|
|
);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
(VOID) SHDeleteKey(hKey, L"NwlnkFwd");
|
|
(VOID) SHDeleteKey(hKey, L"NwlnkFlt");
|
|
RegCloseKey(hKey);
|
|
hKey = NULL;
|
|
}
|
|
|
|
//
|
|
// Restrict ports on non-Enterprise/non-datacenter SKU to
|
|
// 100 per media type
|
|
//
|
|
|
|
//
|
|
// Check server version.
|
|
//
|
|
|
|
hr = S_OK;
|
|
|
|
if (InitializeDialInRestriction())
|
|
{
|
|
//
|
|
// For standard version, limit ports for all media types to a 100
|
|
//
|
|
|
|
//
|
|
// Open key "System\\CurrentControlSet\\Control
|
|
// \\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
|
|
//
|
|
|
|
hr = HrRegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
L"System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",
|
|
KEY_ALL_ACCESS,
|
|
&hKey
|
|
);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Enumerate subkeys
|
|
// - for each key check value of WanEndpoints
|
|
// - if value greater than MAX_DIALIN restrict it to that.
|
|
//
|
|
//
|
|
|
|
DWORD dwIndex = 0;
|
|
WCHAR wcKeyName[MAX_PATH + 1];
|
|
DWORD dwSize = MAX_PATH + 1, dwValue;
|
|
HKEY hEnumKey = NULL;
|
|
FILETIME ft;
|
|
|
|
do
|
|
{
|
|
dwSize = MAX_PATH + 1;
|
|
|
|
hr = HrRegEnumKeyEx(
|
|
hKey,
|
|
dwIndex,
|
|
wcKeyName,
|
|
&dwSize,
|
|
NULL,
|
|
NULL,
|
|
&ft
|
|
);
|
|
|
|
if (HRESULT_CODE(hr) == ERROR_NO_MORE_ITEMS)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_SUCCESS);
|
|
break;
|
|
}
|
|
|
|
if ((HRESULT_CODE(hr) != ERROR_MORE_DATA) &&
|
|
(HRESULT_CODE(hr) != ERROR_SUCCESS))
|
|
{
|
|
dwIndex++;
|
|
continue;
|
|
}
|
|
|
|
hr = HrRegOpenKeyEx(
|
|
hKey,
|
|
wcKeyName,
|
|
KEY_ALL_ACCESS,
|
|
&hEnumKey
|
|
);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
//
|
|
// Move to next key
|
|
//
|
|
|
|
dwIndex++;
|
|
continue;
|
|
}
|
|
|
|
dwValue = 0;
|
|
|
|
hr = HrRegQueryDword(
|
|
hEnumKey,
|
|
L"WanEndPoints",
|
|
&dwValue
|
|
);
|
|
|
|
if (SUCCEEDED(hr) && (dwValue > MAX_ALLOWED_DIALIN))
|
|
{
|
|
HrRegSetDword(
|
|
hEnumKey,
|
|
L"WanEndPoints",
|
|
MAX_ALLOWED_DIALIN
|
|
);
|
|
}
|
|
|
|
RegCloseKey(hEnumKey);
|
|
hEnumKey = NULL;
|
|
dwIndex++;
|
|
|
|
} while( TRUE );
|
|
|
|
RegCloseKey(hKey);
|
|
hKey = NULL;
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
//
|
|
// Since this code may be invoked by non-admin, e.g NetCfgop,
|
|
// when IP addresses etc. are changed, access denied can be
|
|
// ignored in those cases
|
|
//
|
|
|
|
if (HRESULT_CODE(hr) == ERROR_ACCESS_DENIED)
|
|
{
|
|
TraceError ("CSteelhead::HrUpdateRouterConfiguration, "
|
|
"ignoring ", hr);
|
|
hr = HRESULT_FROM_WIN32(ERROR_SUCCESS);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
MprConfigServerDisconnect (m_hMprConfig);
|
|
m_hMprConfig = NULL;
|
|
}
|
|
|
|
TraceError ("CSteelhead::HrUpdateRouterConfiguration", hr);
|
|
return hr;
|
|
}
|
|
|
|
#if (WINVER >= 0x0501)
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member : CSteelhead::HrRemoveIPXRouterConfiguration
|
|
//
|
|
// Purpose: Updates the router configuration to remove all the IPX related
|
|
// configuration
|
|
//
|
|
// Arguments:
|
|
// fRouter - Remove from running instance of router
|
|
//
|
|
// Returns: S_OK or an error code.
|
|
//
|
|
// Author: vraman 17 April 2002
|
|
//
|
|
// Notes:
|
|
//
|
|
|
|
HRESULT
|
|
CSteelhead::HrRemoveIPXRouterConfiguration(
|
|
BOOL fRouter)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
MPR_INTERFACE_0 *ari0;
|
|
DWORD dwIfRead, dwIfTotal, dwIfTransRead, dwIfTransTotal;
|
|
HANDLE hIfTransport;
|
|
|
|
//
|
|
// Enumerate interfaces
|
|
//
|
|
|
|
if (fRouter)
|
|
{
|
|
Assert (m_hMprAdmin);
|
|
hr = HrMprAdminInterfaceEnum(
|
|
m_hMprAdmin,
|
|
0,
|
|
reinterpret_cast<LPBYTE*>(&ari0),
|
|
-1,
|
|
&dwIfRead,
|
|
&dwIfTotal,
|
|
NULL
|
|
);
|
|
}
|
|
else
|
|
{
|
|
hr = HrMprConfigInterfaceEnum(
|
|
m_hMprConfig,
|
|
0,
|
|
reinterpret_cast<LPBYTE*>(&ari0),
|
|
-1,
|
|
&dwIfRead,
|
|
&dwIfTotal,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
for (MPR_INTERFACE_0 *pri0 = ari0; dwIfRead--; pri0++)
|
|
{
|
|
//
|
|
// For each interface, remove RRAS IPX config
|
|
//
|
|
|
|
if (fRouter)
|
|
{
|
|
hr = HrMprAdminInterfaceTransportRemove(
|
|
m_hMprAdmin,
|
|
pri0->hInterface,
|
|
PID_IPX
|
|
);
|
|
}
|
|
else
|
|
{
|
|
hr = HrMprConfigInterfaceTransportGetHandle(
|
|
m_hMprConfig,
|
|
pri0->hInterface,
|
|
PID_IPX,
|
|
&hIfTransport
|
|
);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HrMprConfigInterfaceTransportRemove(
|
|
m_hMprConfig,
|
|
pri0->hInterface,
|
|
hIfTransport
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceError ("CSteelhead::HrRemoveIPXRouterConfiguration", hr);
|
|
return hr;
|
|
}
|
|
|
|
#endif
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// INetCfgComponentControl
|
|
//
|
|
STDMETHODIMP
|
|
CSteelhead::Initialize (
|
|
INetCfgComponent* pncc,
|
|
INetCfg* pnc,
|
|
BOOL fInstalling)
|
|
{
|
|
Validate_INetCfgNotify_Initialize (pncc, pnc, fInstalling);
|
|
|
|
// Hold on to our the component representing us and our host
|
|
// INetCfg object.
|
|
AddRefObj (m_pnccMe = pncc);
|
|
AddRefObj (m_pnc = pnc);
|
|
|
|
m_fUpdateRouterConfiguration = fInstalling;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSteelhead::Validate ()
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSteelhead::CancelChanges ()
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSteelhead::ApplyRegistryChanges ()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!m_fRemoving && m_fUpdateRouterConfiguration)
|
|
{
|
|
m_fUpdateRouterConfiguration = FALSE;
|
|
|
|
TraceTag (ttidRasCfg, "Updating Steelhead configuration.");
|
|
|
|
hr = HrFindOtherComponents ();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HrUpdateRouterConfiguration ();
|
|
|
|
ReleaseOtherComponents ();
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
hr = NETCFG_S_REBOOT;
|
|
}
|
|
}
|
|
|
|
Validate_INetCfgNotify_Apply_Return (hr);
|
|
|
|
TraceError ("CSteelhead::ApplyRegistryChanges",
|
|
(NETCFG_S_REBOOT == hr) ? S_OK : hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// INetCfgComponentSetup
|
|
//
|
|
STDMETHODIMP
|
|
CSteelhead::ReadAnswerFile (
|
|
PCWSTR pszAnswerFile,
|
|
PCWSTR pszAnswerSection)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSteelhead::Install (DWORD dwSetupFlags)
|
|
{
|
|
HRESULT hr;
|
|
|
|
Validate_INetCfgNotify_Install (dwSetupFlags);
|
|
|
|
// Install NdisWan.
|
|
hr = HrInstallComponentOboComponent (m_pnc, NULL,
|
|
GUID_DEVCLASS_NETTRANS,
|
|
c_szInfId_MS_NdisWan,
|
|
m_pnccMe,
|
|
NULL);
|
|
|
|
TraceError ("CSteelhead::Install", hr);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSteelhead::Removing ()
|
|
{
|
|
HRESULT hr;
|
|
|
|
m_fRemoving = TRUE;
|
|
|
|
// Remove NdisWan.
|
|
hr = HrRemoveComponentOboComponent (m_pnc,
|
|
GUID_DEVCLASS_NETTRANS,
|
|
c_szInfId_MS_NdisWan,
|
|
m_pnccMe);
|
|
|
|
TraceError ("CSteelhead::Removing", hr);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSteelhead::Upgrade (
|
|
DWORD dwSetupFlags,
|
|
DWORD dwUpgradeFromBuildNo)
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// INetCfgSystemNotify
|
|
//
|
|
STDMETHODIMP
|
|
CSteelhead::GetSupportedNotifications (
|
|
DWORD* pdwNotificationFlag)
|
|
{
|
|
Validate_INetCfgSystemNotify_GetSupportedNotifications (pdwNotificationFlag);
|
|
|
|
*pdwNotificationFlag = NCN_NET | NCN_NETTRANS |
|
|
NCN_ADD | NCN_REMOVE |
|
|
NCN_PROPERTYCHANGE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSteelhead::SysQueryBindingPath (
|
|
DWORD dwChangeFlag,
|
|
INetCfgBindingPath* pncbp)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSteelhead::SysQueryComponent (
|
|
DWORD dwChangeFlag,
|
|
INetCfgComponent* pncc)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSteelhead::SysNotifyBindingPath (
|
|
DWORD dwChangeFlag,
|
|
INetCfgBindingPath* pncbp)
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSteelhead::SysNotifyComponent (
|
|
DWORD dwChangeFlag,
|
|
INetCfgComponent* pncc)
|
|
{
|
|
HRESULT hr;
|
|
|
|
Validate_INetCfgSystemNotify_SysNotifyComponent (dwChangeFlag, pncc);
|
|
|
|
// Assume we won't be dirty as a result of this notification.
|
|
//
|
|
hr = S_FALSE;
|
|
|
|
if (!m_fUpdateRouterConfiguration)
|
|
{
|
|
// If we're being called for a change to a net device, make sure
|
|
// its physical before deciding we need to update our configuration.
|
|
//
|
|
GUID guidClass;
|
|
hr = pncc->GetClassGuid (&guidClass);
|
|
if (S_OK == hr)
|
|
{
|
|
if (GUID_DEVCLASS_NET == guidClass)
|
|
{
|
|
hr = HrShouldRouteOverAdapter (pncc, NULL);
|
|
if (S_OK == hr)
|
|
{
|
|
TraceTag (ttidRasCfg, "CSteelhead::SysNotifyComponent: "
|
|
"called for adapter install/remove.");
|
|
|
|
m_fUpdateRouterConfiguration = TRUE;
|
|
Assert (S_OK == hr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TraceTag (ttidRasCfg, "CSteelhead::SysNotifyComponent: "
|
|
"called for protocol add/remove/change.");
|
|
|
|
// If we're called for non-net devices, we want to
|
|
// update our configuration. (GetSupportedNotifications
|
|
// controls how often we fall into this.)
|
|
//
|
|
m_fUpdateRouterConfiguration = TRUE;
|
|
Assert (S_OK == hr);
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, (S_FALSE == hr),
|
|
"CSteelhead::SysNotifyComponent", hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
#if (WINVER >= 0x0501)
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member : InitializeDialInRestriction
|
|
//
|
|
// Purpose: Checks if the upgrade is to the enterprise or datacenter
|
|
// edition of server. If so there is no restriction on the
|
|
// number of dialin ports. Otherwise the max number should
|
|
// be restricted to a 100.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: TRUE if dailin restriction is required, false otherwise
|
|
//
|
|
// Author: vraman, 30 August 2002
|
|
//
|
|
// Notes:
|
|
//
|
|
|
|
|
|
BOOL
|
|
InitializeDialInRestriction()
|
|
{
|
|
OSVERSIONINFOEX osvi;
|
|
ULONGLONG ConditionMask;
|
|
BOOL bRestrictDialIn = TRUE;
|
|
|
|
//
|
|
// if its a server and the flavour is not Enterprise (ads) or DataCenter
|
|
// apply the restriction. Note his doesn't take care of various other
|
|
// combinations like embedded/blade, etc.
|
|
//
|
|
|
|
ConditionMask = 0;
|
|
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
|
|
|
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
|
osvi.wProductType = (USHORT)VER_NT_SERVER;
|
|
|
|
VER_SET_CONDITION(ConditionMask, VER_PRODUCT_TYPE, VER_EQUAL);
|
|
|
|
if(VerifyVersionInfo(&osvi, VER_PRODUCT_TYPE, ConditionMask))
|
|
{
|
|
//
|
|
// Upgrade is to a server version
|
|
//
|
|
|
|
ConditionMask = 0;
|
|
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
|
|
|
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
|
osvi.wSuiteMask = VER_SUITE_ENTERPRISE
|
|
| VER_SUITE_DATACENTER
|
|
| VER_SUITE_SECURITY_APPLIANCE;
|
|
|
|
VER_SET_CONDITION(ConditionMask, VER_SUITENAME, VER_OR);
|
|
|
|
if(VerifyVersionInfo(&osvi, VER_SUITENAME, ConditionMask))
|
|
{
|
|
//
|
|
// Upgrade is to a enterprise or datacenter edition
|
|
// Do not restrict server edition
|
|
//
|
|
|
|
bRestrictDialIn = FALSE;
|
|
}
|
|
}
|
|
|
|
return bRestrictDialIn;
|
|
}
|
|
|
|
#endif
|