1606 lines
47 KiB
C++
1606 lines
47 KiB
C++
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// 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 "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;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// 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 )) ))
|
||
|
{
|
||
|
hr = HrEnsureIpxRouterInterfacesForAdapter (pszBindName);
|
||
|
}
|
||
|
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,
|
||
|
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 ()
|
||
|
{
|
||
|
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);
|
||
|
MprAdminServerDisconnect (m_hMprAdmin);
|
||
|
m_hMprAdmin = NULL;
|
||
|
}
|
||
|
|
||
|
MprConfigServerDisconnect (m_hMprConfig);
|
||
|
m_hMprConfig = NULL;
|
||
|
}
|
||
|
|
||
|
TraceError ("CSteelhead::HrUpdateRouterConfiguration", hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
// 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;
|
||
|
}
|