|
|
//+---------------------------------------------------------------------------
//
// 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; }
|