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.
576 lines
14 KiB
576 lines
14 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1997-2000.
|
|
//
|
|
// File: B I N D C F G . C P P
|
|
//
|
|
// Contents: Exposes control for creating and removing RAS bindings.
|
|
//
|
|
// Notes: The exported methods are called by RAS when endpoints
|
|
// need to be created or removed for the purpose of making
|
|
// calls.
|
|
//
|
|
// Author: shaunco 16 Oct 1998
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "pch.h"
|
|
#pragma hdrstop
|
|
#include "ncnetcfg.h"
|
|
#include "ncutil.h"
|
|
#include "netcfgn.h"
|
|
#include <rasapip.h>
|
|
|
|
extern const WCHAR c_szInfId_MS_NdisWanIp[];
|
|
extern const WCHAR c_szInfId_MS_NdisWanNbfIn[];
|
|
extern const WCHAR c_szInfId_MS_NdisWanNbfOut[];
|
|
extern const WCHAR c_szInfId_MS_NetBEUI[];
|
|
extern const WCHAR c_szInfId_MS_TCPIP[];
|
|
|
|
class CRasBindingConfig
|
|
{
|
|
public:
|
|
INetCfg* m_pNetCfg;
|
|
BOOL m_fInitCom;
|
|
|
|
enum NEEDED_COMPONENTS
|
|
{
|
|
INDEX_IP = 0,
|
|
INDEX_NBF,
|
|
INDEX_IPADAPTER,
|
|
COUNT_COMPONENTS,
|
|
};
|
|
INetCfgComponent* m_apComponents [COUNT_COMPONENTS];
|
|
|
|
public:
|
|
#if DBG
|
|
CRasBindingConfig ()
|
|
{
|
|
m_pNetCfg = NULL;
|
|
}
|
|
~CRasBindingConfig ()
|
|
{
|
|
AssertH (!m_pNetCfg);
|
|
}
|
|
#endif
|
|
|
|
public:
|
|
HRESULT
|
|
HrAddOrRemoveBindings (
|
|
IN DWORD dwFlags,
|
|
IN OUT UINT* pcIpOut,
|
|
IN const GUID* pguidIpOutBindings,
|
|
IN OUT UINT* pcNbfIn,
|
|
IN OUT UINT* pcNbfOut);
|
|
|
|
HRESULT
|
|
HrCountBindings (
|
|
OUT UINT* pcIpOut,
|
|
OUT UINT* pcNbfIn,
|
|
OUT UINT* pcNbfOut);
|
|
|
|
HRESULT
|
|
HrLoadINetCfg (
|
|
IN REGSAM samDesired);
|
|
|
|
HRESULT
|
|
HrLoadINetCfgAndAddOrRemoveBindings (
|
|
IN DWORD dwFlags,
|
|
IN OUT UINT* pcIpOut,
|
|
IN const GUID* pguidIpOutBindings,
|
|
IN OUT UINT* pcNbfIn,
|
|
IN OUT UINT* pcNbfOut);
|
|
|
|
VOID
|
|
UnloadINetCfg ();
|
|
|
|
INetCfgComponent*
|
|
PnccIp ()
|
|
{
|
|
AssertH (m_pNetCfg);
|
|
return m_apComponents [INDEX_IP];
|
|
}
|
|
|
|
INetCfgComponent*
|
|
PnccIpAdapter ()
|
|
{
|
|
AssertH (m_pNetCfg);
|
|
return m_apComponents [INDEX_IPADAPTER];
|
|
}
|
|
|
|
INetCfgComponent*
|
|
PnccNbf ()
|
|
{
|
|
AssertH (m_pNetCfg);
|
|
return m_apComponents [INDEX_NBF];
|
|
}
|
|
};
|
|
|
|
|
|
HRESULT
|
|
CRasBindingConfig::HrCountBindings (
|
|
UINT* pcIpOut,
|
|
UINT* pcNbfIn,
|
|
UINT* pcNbfOut)
|
|
{
|
|
Assert (pcIpOut);
|
|
Assert (pcNbfIn);
|
|
Assert (pcNbfOut);
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// Initialize output parameters.
|
|
//
|
|
*pcIpOut = *pcNbfIn = *pcNbfOut = 0;
|
|
|
|
if (PnccIp() && PnccIpAdapter())
|
|
{
|
|
INetCfgComponentUpperEdge* pUpperEdge;
|
|
hr = HrQueryNotifyObject (
|
|
PnccIp(),
|
|
IID_INetCfgComponentUpperEdge,
|
|
reinterpret_cast<VOID**>(&pUpperEdge));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
DWORD dwNumInterfaces;
|
|
GUID* pguidInterfaceIds;
|
|
|
|
hr = pUpperEdge->GetInterfaceIdsForAdapter (
|
|
PnccIpAdapter(),
|
|
&dwNumInterfaces,
|
|
&pguidInterfaceIds);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*pcIpOut = dwNumInterfaces;
|
|
|
|
CoTaskMemFree (pguidInterfaceIds);
|
|
}
|
|
|
|
ReleaseObj (pUpperEdge);
|
|
}
|
|
}
|
|
|
|
if (PnccNbf())
|
|
{
|
|
// Iterate adapters in the system.
|
|
//
|
|
CIterNetCfgComponent nccIter(m_pNetCfg, &GUID_DEVCLASS_NET);
|
|
INetCfgComponent* pnccAdapter;
|
|
|
|
while (S_OK == (hr = nccIter.HrNext (&pnccAdapter)))
|
|
{
|
|
// Quickly discard non-hidden adapters to avoid unneccesary
|
|
// string compares.
|
|
//
|
|
DWORD dwCharacter;
|
|
if ( SUCCEEDED(pnccAdapter->GetCharacteristics (&dwCharacter))
|
|
&& (dwCharacter & NCF_HIDDEN))
|
|
{
|
|
PWSTR pszId;
|
|
if (SUCCEEDED(pnccAdapter->GetId (&pszId)))
|
|
{
|
|
if (FEqualComponentId (c_szInfId_MS_NdisWanNbfIn,
|
|
pszId))
|
|
{
|
|
(*pcNbfIn)++;
|
|
}
|
|
else if (FEqualComponentId (c_szInfId_MS_NdisWanNbfOut,
|
|
pszId))
|
|
{
|
|
(*pcNbfOut)++;
|
|
}
|
|
|
|
CoTaskMemFree (pszId);
|
|
}
|
|
}
|
|
ReleaseObj (pnccAdapter);
|
|
}
|
|
|
|
}
|
|
|
|
TraceTag (ttidRasCfg,
|
|
"Current RAS bindings: "
|
|
"%u IP dial-out, %u NBF dial-in, %u NBF dial-out",
|
|
*pcIpOut, *pcNbfIn, *pcNbfOut);
|
|
|
|
// Normalize the HRESULT. (i.e. don't return S_FALSE)
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CRasBindingConfig::HrCountBindings");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CRasBindingConfig::HrAddOrRemoveBindings (
|
|
IN DWORD dwFlags,
|
|
IN OUT UINT* pcIpOut,
|
|
IN const GUID* pguidIpOutBindings,
|
|
IN OUT UINT* pcNbfIn,
|
|
IN OUT UINT* pcNbfOut)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Safe off the input parameters.
|
|
//
|
|
UINT cIpOut = *pcIpOut;
|
|
UINT cNbfIn = *pcNbfIn;
|
|
UINT cNbfOut = *pcNbfOut;
|
|
|
|
if (cIpOut && PnccIp() && PnccIpAdapter())
|
|
{
|
|
INetCfgComponentUpperEdge* pUpperEdge;
|
|
hr = HrQueryNotifyObject (
|
|
PnccIp(),
|
|
IID_INetCfgComponentUpperEdge,
|
|
reinterpret_cast<VOID**>(&pUpperEdge));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (dwFlags & ARA_ADD)
|
|
{
|
|
TraceTag (ttidRasCfg,
|
|
"Adding %d TCP/IP interfaces to the ndiswanip adapter",
|
|
cIpOut);
|
|
|
|
hr = pUpperEdge->AddInterfacesToAdapter (
|
|
PnccIpAdapter(),
|
|
cIpOut);
|
|
}
|
|
else
|
|
{
|
|
TraceTag (ttidRasCfg,
|
|
"Removing %d TCP/IP interfaces from the ndiswanip adapter",
|
|
cIpOut);
|
|
|
|
hr = pUpperEdge->RemoveInterfacesFromAdapter (
|
|
PnccIpAdapter(),
|
|
cIpOut,
|
|
pguidIpOutBindings);
|
|
}
|
|
|
|
ReleaseObj (pUpperEdge);
|
|
}
|
|
}
|
|
|
|
if (PnccNbf() && SUCCEEDED(hr))
|
|
{
|
|
if (cNbfIn)
|
|
{
|
|
TraceTag (ttidRasCfg,
|
|
"%s %d %S adapters",
|
|
(dwFlags & ARA_ADD) ? "Adding" : "Removing",
|
|
cNbfIn,
|
|
c_szInfId_MS_NdisWanNbfIn);
|
|
|
|
hr = HrAddOrRemoveAdapter (
|
|
m_pNetCfg,
|
|
c_szInfId_MS_NdisWanNbfIn,
|
|
dwFlags, NULL, cNbfIn, NULL);
|
|
}
|
|
|
|
if (cNbfOut && SUCCEEDED(hr))
|
|
{
|
|
TraceTag (ttidRasCfg,
|
|
"%s %d %S adapters",
|
|
(dwFlags & ARA_ADD) ? "Adding" : "Removing",
|
|
cNbfOut,
|
|
c_szInfId_MS_NdisWanNbfOut);
|
|
|
|
hr = HrAddOrRemoveAdapter (
|
|
m_pNetCfg,
|
|
c_szInfId_MS_NdisWanNbfOut,
|
|
dwFlags, NULL, cNbfOut, NULL);
|
|
}
|
|
}
|
|
|
|
HRESULT hrT = HrCountBindings(pcIpOut, pcNbfIn, pcNbfOut);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = hrT;
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CRasBindingConfig::HrAddOrRemoveBindings");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CRasBindingConfig::HrLoadINetCfg (
|
|
IN REGSAM samDesired)
|
|
{
|
|
HRESULT hr;
|
|
|
|
Assert (!m_pNetCfg);
|
|
|
|
// Get INetCfg and lock it for write.
|
|
//
|
|
m_fInitCom = TRUE;
|
|
hr = HrCreateAndInitializeINetCfg (
|
|
&m_fInitCom,
|
|
&m_pNetCfg,
|
|
(KEY_WRITE == samDesired), // get the write lock if needed
|
|
0, // don't wait for it
|
|
L"RAS Binding Configuration",
|
|
NULL);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ZeroMemory (m_apComponents, sizeof(m_apComponents));
|
|
|
|
// Find the following components and hold on to their INetCfgComponent
|
|
// interface pointers in m_apComponents. UnloadINetCfg will release
|
|
// these. HrFindComponents will zero the array so it is safe to
|
|
// call UnloadINetCfg if HrFindComponents fails.
|
|
//
|
|
const GUID* c_apguidComponentClasses [COUNT_COMPONENTS] =
|
|
{
|
|
&GUID_DEVCLASS_NETTRANS, // Ip
|
|
&GUID_DEVCLASS_NETTRANS, // NetBEUI
|
|
&GUID_DEVCLASS_NET, // IpAdapter
|
|
};
|
|
|
|
const PCWSTR c_apszComponentIds [COUNT_COMPONENTS] =
|
|
{
|
|
c_szInfId_MS_TCPIP,
|
|
c_szInfId_MS_NetBEUI,
|
|
c_szInfId_MS_NdisWanIp,
|
|
};
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HrFindComponents (
|
|
m_pNetCfg,
|
|
COUNT_COMPONENTS,
|
|
c_apguidComponentClasses,
|
|
c_apszComponentIds,
|
|
m_apComponents);
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
// If we have a failure while trying to find these components
|
|
// we're going to fail this method call, so be sure to cleanup
|
|
// m_pNetCfg.
|
|
//
|
|
UnloadINetCfg ();
|
|
Assert (!m_pNetCfg);
|
|
}
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CRasBindingConfig::HrLoadINetCfg");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CRasBindingConfig::HrLoadINetCfgAndAddOrRemoveBindings (
|
|
IN DWORD dwFlags,
|
|
IN OUT UINT* pcIpOut,
|
|
IN const GUID* pguidIpOutBindings,
|
|
IN OUT UINT* pcNbfIn,
|
|
IN OUT UINT* pcNbfOut)
|
|
{
|
|
Assert (!m_pNetCfg);
|
|
|
|
HRESULT hr;
|
|
|
|
hr = HrLoadINetCfg (KEY_WRITE);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
try
|
|
{
|
|
hr = HrAddOrRemoveBindings (
|
|
dwFlags,
|
|
pcIpOut,
|
|
pguidIpOutBindings,
|
|
pcNbfIn,
|
|
pcNbfOut);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
(VOID) m_pNetCfg->Apply();
|
|
}
|
|
else
|
|
{
|
|
(VOID) m_pNetCfg->Cancel();
|
|
}
|
|
}
|
|
catch (bad_alloc)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
UnloadINetCfg ();
|
|
}
|
|
|
|
// We shouldn't ever leave with an un-released INetCfg.
|
|
//
|
|
Assert (!m_pNetCfg);
|
|
|
|
TraceHr (ttidError, FAL, hr, (NETCFG_S_REBOOT == hr),
|
|
"CRasBindingConfig::HrLoadINetCfgAndAddOrRemoveBindings");
|
|
return hr;
|
|
}
|
|
|
|
VOID
|
|
CRasBindingConfig::UnloadINetCfg ()
|
|
{
|
|
// Must call HrLoadINetCfg before calling this.
|
|
//
|
|
Assert (m_pNetCfg);
|
|
|
|
ReleaseIUnknownArray (COUNT_COMPONENTS, (IUnknown**)m_apComponents);
|
|
|
|
(VOID) HrUninitializeAndReleaseINetCfg (m_fInitCom, m_pNetCfg, TRUE);
|
|
m_pNetCfg = NULL;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Exported functions
|
|
//
|
|
|
|
EXTERN_C
|
|
HRESULT
|
|
WINAPI
|
|
RasAddBindings (
|
|
IN OUT UINT* pcIpOut,
|
|
IN OUT UINT* pcNbfIn,
|
|
IN OUT UINT* pcNbfOut)
|
|
{
|
|
HRESULT hr;
|
|
|
|
#if 0
|
|
RtlValidateProcessHeaps ();
|
|
#endif
|
|
|
|
// Validate parameters.
|
|
//
|
|
if (!pcIpOut || !pcNbfIn || !pcNbfOut)
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else if (!*pcIpOut && !*pcNbfIn && !*pcNbfOut)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
CRasBindingConfig Config;
|
|
|
|
hr = Config.HrLoadINetCfgAndAddOrRemoveBindings (
|
|
ARA_ADD,
|
|
pcIpOut,
|
|
NULL,
|
|
pcNbfIn,
|
|
pcNbfOut);
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CRasBindingConfig::RasAddBindings");
|
|
return hr;
|
|
}
|
|
|
|
EXTERN_C
|
|
HRESULT
|
|
WINAPI
|
|
RasCountBindings (
|
|
OUT UINT* pcIpOut,
|
|
OUT UINT* pcNbfIn,
|
|
OUT UINT* pcNbfOut)
|
|
{
|
|
HRESULT hr;
|
|
|
|
#if 0
|
|
RtlValidateProcessHeaps ();
|
|
#endif
|
|
|
|
// Validate parameters.
|
|
//
|
|
if (!pcIpOut || !pcNbfIn || !pcNbfOut)
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else
|
|
{
|
|
CRasBindingConfig Config;
|
|
|
|
hr = Config.HrLoadINetCfg (KEY_READ);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
try
|
|
{
|
|
hr = Config.HrCountBindings (
|
|
pcIpOut,
|
|
pcNbfIn,
|
|
pcNbfOut);
|
|
}
|
|
catch (bad_alloc)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
Config.UnloadINetCfg ();
|
|
}
|
|
// We shouldn't ever leave with an un-released INetCfg.
|
|
//
|
|
Assert (!Config.m_pNetCfg);
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CRasBindingConfig::RasCountBindings");
|
|
return hr;
|
|
}
|
|
|
|
EXTERN_C
|
|
HRESULT
|
|
WINAPI
|
|
RasRemoveBindings (
|
|
IN OUT UINT* pcIpOutBindings,
|
|
IN const GUID* pguidIpOutBindings,
|
|
IN OUT UINT* pcNbfIn,
|
|
IN OUT UINT* pcNbfOut)
|
|
{
|
|
HRESULT hr;
|
|
|
|
#if 0
|
|
RtlValidateProcessHeaps ();
|
|
#endif
|
|
|
|
// Validate parameters.
|
|
//
|
|
if (!pcIpOutBindings || !pcNbfIn || !pcNbfOut)
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else if (!*pcIpOutBindings && !*pcNbfIn && !*pcNbfOut)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else if (*pcIpOutBindings && !pguidIpOutBindings)
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else
|
|
{
|
|
CRasBindingConfig Config;
|
|
|
|
hr = Config.HrLoadINetCfgAndAddOrRemoveBindings (
|
|
ARA_REMOVE,
|
|
pcIpOutBindings,
|
|
pguidIpOutBindings,
|
|
pcNbfIn,
|
|
pcNbfOut);
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CRasBindingConfig::RasRemoveBindings");
|
|
return hr;
|
|
}
|