windows-nt/Source/XPSP1/NT/net/config/samples/muxim/notify.cpp
2020-09-26 16:20:57 +08:00

2111 lines
55 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992-2001.
//
// File: N O T I F Y . C P P
//
// Contents: Sample notify object code
//
// Notes:
//
// Author: Alok Sinha
//----------------------------------------------------------------------------
#include "notify.h"
HRESULT HrCopyMiniportInf (VOID);
//----------------------------------------------------------------------------
//
// Function: CMuxNotify::CMuxNotify
//
// Purpose: Constructor for CMuxNotify
//
// Arguments: None
//
// Returns: None
//
// Notes:
//
CMuxNotify::CMuxNotify (VOID) : m_pncc (NULL),
m_pnc(NULL),
m_eApplyAction(eActUnknown),
m_pUnkContext(NULL)
{
TraceMsg( L"-->CMuxNotify::CMuxNotify(Constructor).\n" );
TraceMsg( L"<--CMuxNotify::CMuxNotify(Constructor).\n" );
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::~CMuxNotify
//
// Purpose: Destructor for class CMuxNotify
//
// Arguments: None
//
// Returns: None
//
// Notes:
//
CMuxNotify::~CMuxNotify (VOID)
{
CMuxPhysicalAdapter *pAdapter;
DWORD dwAdapterCount;
DWORD i;
TraceMsg( L"-->CMuxNotify::~CMuxNotify(Destructor).\n" );
// release interfaces if acquired
ReleaseObj( m_pncc );
ReleaseObj( m_pnc );
ReleaseObj( m_pUnkContext );
dwAdapterCount = m_AdaptersList.ListCount();
for (i=0; i < dwAdapterCount; ++i) {
m_AdaptersList.Remove( &pAdapter );
delete pAdapter;
}
dwAdapterCount = m_AdaptersToRemove.ListCount();
for (i=0; i < dwAdapterCount; ++i) {
m_AdaptersToRemove.Remove( &pAdapter );
delete pAdapter;
}
dwAdapterCount = m_AdaptersToAdd.ListCount();
for (i=0; i < dwAdapterCount; ++i) {
m_AdaptersToAdd.Remove( &pAdapter );
delete pAdapter;
}
TraceMsg( L"<--CMuxNotify::~CMuxNotify(Destructor).\n" );
}
//
//---------------------- NOTIFY OBJECT FUNCTIONS -----------------------------
//
//----------------------------------------------------------------------------
// INetCfgComponentControl
//
// The following functions provide the INetCfgComponentControl interface.
//
//----------------------------------------------------------------------------
//
// Function: CMuxNotify::Initialize
//
// Purpose: Initialize the notify object
//
// Arguments:
// IN pnccItem : Pointer to INetCfgComponent object
// IN pnc : Pointer to INetCfg object
// IN fInstalling: TRUE if we are being installed
//
// Returns:
//
// Notes:
//
STDMETHODIMP CMuxNotify::Initialize (INetCfgComponent* pncc,
INetCfg* pnc,
BOOL fInstalling)
{
HRESULT hr = S_OK;
TraceMsg( L"-->CMuxNotify INetCfgControl::Initialize.\n" );
// Save INetCfg & INetCfgComponent and add a refcount
m_pncc = pncc;
m_pnc = pnc;
if (m_pncc) {
m_pncc->AddRef();
}
if (m_pnc) {
m_pnc->AddRef();
}
//
// If this not an installation, then we need to
// initialize all of our data and classes
//
if ( !fInstalling ) {
hr = HrLoadAdapterConfiguration();
}else {
OSVERSIONINFO osvi;
ZeroMemory( &osvi,
sizeof(OSVERSIONINFO) );
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if ( GetVersionEx(&osvi) )
{
if ( (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
(osvi.dwMajorVersion == 5) &&
(osvi.dwMinorVersion == 0) )
{
// On Windows 2000, copy the miniport inf file to %windir%\inf.
TraceMsg(L" Copying miniport inf to system inf directory...\n");
HrCopyMiniportInf();
}
else
{
TraceMsg(L" Skipping copying miniport inf to system inf directory...\n");
}
}
}
TraceMsg( L"<--CMuxNotify INetCfgControl::Initialize(HRESULT = %x).\n",
hr );
return hr;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::CancelChanges
//
// Purpose: Cancel any changes made to internal data
//
// Arguments: None
//
// Returns: S_OK on success, otherwise an error code
//
// Notes:
//
STDMETHODIMP CMuxNotify::CancelChanges (VOID)
{
TraceMsg( L"-->CMuxNotify INetCfgControl::CancelChanges.\n" );
TraceMsg( L"<--CMuxNotify INetCfgControl::CancelChanges(HRESULT = %x).\n",
S_OK );
return S_OK;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::ApplyRegistryChanges
//
// Purpose: Apply changes.
//
// Arguments: None
//
// Returns: S_OK.
//
// Notes: We can make changes to registry etc. here.
STDMETHODIMP CMuxNotify::ApplyRegistryChanges(VOID)
{
CMuxPhysicalAdapter *pAdapter = NULL;
GUID guidAdapter;
DWORD dwAdapterCount;
DWORD i;
TraceMsg( L"-->CMuxNotify INetCfgControl::ApplyRegistryChanges.\n" );
//
// Make registry changes for the adapters added.
//
dwAdapterCount = m_AdaptersToAdd.ListCount();
TraceMsg( L" Adding %d new adapters.\n",
dwAdapterCount );
for (i=0; i < dwAdapterCount; ++i) {
m_AdaptersToAdd.Find( i,
&pAdapter );
pAdapter->ApplyRegistryChanges( eActAdd );
}
//
// Make registry changes for the adapters uninstalled.
//
dwAdapterCount = m_AdaptersToRemove.ListCount();
TraceMsg( L" Removing %d adapters.\n",
dwAdapterCount );
for (i=0; i < dwAdapterCount; ++i) {
m_AdaptersToRemove.Find( i,
&pAdapter );
pAdapter->ApplyRegistryChanges( eActRemove );
}
//
// Make registry changes for the miniports added/removed
// through the property pages.
//
dwAdapterCount = m_AdaptersList.ListCount();
for (i=0; i < dwAdapterCount; ++i) {
m_AdaptersList.Find( i,
&pAdapter );
pAdapter->ApplyRegistryChanges( eActUpdate );
}
TraceMsg( L"<--CMuxNotify INetCfgControl::ApplyRegistryChanges(HRESULT = %x).\n",
S_OK );
return S_OK;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::ApplyPnpChanges
//
// Purpose: Apply changes.
//
// Arguments:
// IN pfCallback: PnPConfigCallback interface.
//
// Returns: S_OK.
//
// Notes:
STDMETHODIMP CMuxNotify::ApplyPnpChanges (
INetCfgPnpReconfigCallback* pfCallback)
{
CMuxPhysicalAdapter *pAdapter = NULL;
GUID guidAdapter;
DWORD dwAdapterCount;
DWORD i;
TraceMsg( L"-->CMuxNotify INetCfgControl::ApplyPnpChanges.\n" );
//
// Apply PnP changes for the adapters added.
//
dwAdapterCount = m_AdaptersToAdd.ListCount();
TraceMsg( L" Applying PnP changes when %d adapters added.\n",
dwAdapterCount );
for (i=0; i < dwAdapterCount; ++i) {
m_AdaptersToAdd.Remove( &pAdapter );
pAdapter->ApplyPnpChanges( pfCallback,
eActAdd );
pAdapter->GetAdapterGUID( &guidAdapter );
m_AdaptersList.Insert( pAdapter,
guidAdapter );
}
//
// Apply PnP changes for the adapters uninstalled.
//
dwAdapterCount = m_AdaptersToRemove.ListCount();
TraceMsg( L" Applying PnP changes when %d adapters removed.\n",
dwAdapterCount );
for (i=0; i < dwAdapterCount; ++i) {
m_AdaptersToRemove.Remove( &pAdapter );
pAdapter->ApplyPnpChanges( pfCallback,
eActRemove );
delete pAdapter;
}
//
// Apply PnP changes for the miniports added/removed through
// the property pages.
//
dwAdapterCount = m_AdaptersList.ListCount();
for (i=0; i < dwAdapterCount; ++i) {
m_AdaptersList.Find( i,
&pAdapter );
pAdapter->ApplyPnpChanges( pfCallback,
eActUpdate );
}
TraceMsg( L"<--CMuxNotify INetCfgControl::ApplyPnpChanges(HRESULT = %x).\n",
S_OK );
return S_OK;
}
//----------------------------------------------------------------------------
// INetCfgComponentSetup
//
// The following functions provide the INetCfgComponentSetup interface.
//
//----------------------------------------------------------------------------
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::Install
//
// Purpose: Do operations necessary during the installation.
//
// Arguments:
// IN dwSetupFlags: Setup flags
//
// Returns: S_OK
//
// Notes: Don't do anything irreversible (like modifying registry) yet
// since the config. actually completes only when Apply is called!
//
STDMETHODIMP CMuxNotify::Install (DWORD dwSetupFlags)
{
TraceMsg( L"-->CMuxNotify INetCfgSetup::Install.\n" );
// Start up the install process
m_eApplyAction = eActInstall;
TraceMsg( L"<--CMuxNotify INetCfgSetup::Install(HRESULT = %x).\n",
S_OK );
return S_OK;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::Upgrade
//
// Purpose: Do operations necessary during the upgrade.
//
// Arguments:
// IN dwSetupFlags: Setup flags
//
// Returns: S_OK
//
// Notes: Don't do anything irreversible (like modifying registry) yet
// since the config. actually completes only when Apply is called!
//
STDMETHODIMP CMuxNotify::Upgrade (IN DWORD dwSetupFlags,
IN DWORD dwUpgradeFromBuildNo)
{
TraceMsg( L"-->CMuxNotify INetCfgSetup::Upgrade.\n" );
TraceMsg( L" DwSetupFlags = %x, dwUpgradeFromBuildNo = %x\n",
dwSetupFlags,
dwUpgradeFromBuildNo );
TraceMsg( L"<--CMuxNotify INetCfgSetup::Upgrade(HRESULT = %x).\n",
S_OK );
return S_OK;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::ReadAnswerFile
//
// Purpose: Read settings from answerfile and configure CMuxNotify
//
// Arguments:
// IN pszAnswerFile : Name of AnswerFile
// IN pszAnswerSection: Name of parameters section
//
// Returns:
//
// Notes: Don't do anything irreversible (like modifying registry) yet
// since the config. actually completes only when Apply is called!
//
STDMETHODIMP CMuxNotify::ReadAnswerFile (PCWSTR pszAnswerFile,
PCWSTR pszAnswerSection)
{
PCWSTR pszParamReadFromAnswerFile = L"ParamFromAnswerFile";
TraceMsg( L"-->CMuxNotify INetCfgSetup::ReadAnswerFile.\n" );
// We will pretend here that szParamReadFromAnswerFile was actually
// read from the AnswerFile using the following steps
//
// - Open file pszAnswerFile using SetupAPI
// - locate section pszAnswerSection
// - locate the required key and get its value
// - store its value in pszParamReadFromAnswerFile
// - close HINF for pszAnswerFile
// Now that we have read pszParamReadFromAnswerFile from the
// AnswerFile, store it in our memory structure.
// Remember we should not be writing it to the registry till
// our Apply is called!!
//
TraceMsg( L"<--CMuxNotify INetCfgSetup::ReadAnswerFile(HRESULT = %x).\n",
S_OK );
return S_OK;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::Removing
//
// Purpose: Do necessary cleanup when being removed
//
// Arguments: None
//
// Returns: S_OK
//
// Notes: Don't do anything irreversible (like modifying registry) yet
// since the removal is actually complete only when Apply is called!
//
STDMETHODIMP CMuxNotify::Removing (VOID)
{
TraceMsg( L"-->CMuxNotify INetCfgSetup::Removing.\n" );
TraceMsg( L"<--CMuxNotify INetCfgSetup::Removing(HRESULT = %x).\n",
S_OK );
return S_OK;
}
//----------------------------------------------------------------------------
// INetCfgComponentNotifyBinding
//
// The following functions provide the INetCfgComponentNotifyBinding interface.
//
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//
// Function: CMuxNotify::QueryBindingPath
//
// Purpose: This is specific to the component being installed. This will
// ask us if we want to bind to the Item being passed into
// this routine. We can disable the binding by returning
// NETCFG_S_DISABLE_QUERY
//
//
// Arguments:
// IN dwChangeFlag: Type of binding change
// IN pncbpItem : Pointer to INetCfgBindingPath object
//
// Returns: S_OK on success, otherwise an error code.
//
// Notes:
//
STDMETHODIMP CMuxNotify::QueryBindingPath (IN DWORD dwChangeFlag,
IN INetCfgBindingPath *pncbp)
{
TraceMsg( L"-->CMuxNotify INetCfgNotifyBinding::QueryBindingPath.\n" );
DumpChangeFlag( dwChangeFlag );
DumpBindingPath( pncbp );
TraceMsg( L"<--CMuxNotify INetCfgNotifyBinding::QueryBindingPath(HRESULT = %x).\n",
S_OK );
return S_OK;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::NotifyBindingPath
//
// Purpose: We are now being told to bind to the component passed to us.
//
//
// Arguments:
// IN dwChangeFlag: Type of system change
// IN pncc : Pointer to INetCfgComponent object
//
// Returns: S_OK on success, otherwise an error code
//
// Notes:
//
STDMETHODIMP CMuxNotify::NotifyBindingPath (IN DWORD dwChangeFlag,
IN INetCfgBindingPath *pncbp)
{
INetCfgComponent *pnccLower;
INetCfgComponent *pnccUpper;
LPWSTR pszwInfIdLower;
LPWSTR pszwInfIdUpper;
DWORD dwCharcteristics;
HRESULT hr = S_OK;
TraceMsg( L"-->CMuxNotify INetCfgNotifyBinding::NotifyBindingPath.\n" );
DumpChangeFlag( dwChangeFlag );
DumpBindingPath( pncbp );
//
// We are only interested to know 1) when a component is installed
// and we are binding to it i.e. dwChangeFlag = NCN_ADD | NCN_ENABLE
// and 2) when a component is removed to which we are bound i.e.
// dwChangeFlag = NCN_REMOVE | NCN_ENABLE. dwChangeFlag is never
// set to NCN_ADD or NCN_REMOVE only. So, checking for NCN_ENABLE
// covers the case of NCN_ADD | NCN_ENABLE and checking for NCN_REMOVE
// covers the case of NCN_REMOVE | NCN_ENABLE. We don't care about
// NCN_ADD | NCN_DISABLE (case 1) and NCN_REMOVE | NCN_DISABLE (case 2).
//
if ( dwChangeFlag & (NCN_ENABLE | NCN_REMOVE) ) {
//
// Get the upper and lower components.
//
hr = HrGetUpperAndLower( pncbp,
&pnccUpper,
&pnccLower );
if ( hr == S_OK ) {
hr = pnccLower->GetCharacteristics( &dwCharcteristics );
if ( hr == S_OK ) {
hr = pnccLower->GetId( &pszwInfIdLower );
if ( hr == S_OK ) {
hr = pnccUpper->GetId( &pszwInfIdUpper );
if ( hr == S_OK ) {
//
// We are interested only in binding to a
// physical ethernet adapters.
//
if ( dwCharcteristics & NCF_PHYSICAL ) {
if ( !_wcsicmp( pszwInfIdUpper, c_szMuxProtocol ) ) {
if ( dwChangeFlag & NCN_ADD ) {
hr = HrAddAdapter( pnccLower );
m_eApplyAction = eActAdd;
} else if ( dwChangeFlag & NCN_REMOVE ) {
hr = HrRemoveAdapter( pnccLower );
m_eApplyAction = eActRemove;
}
}
} // Physical Adapters.
else if (dwCharcteristics & NCF_VIRTUAL) {
}
CoTaskMemFree( pszwInfIdUpper );
} // Got the upper component id.
CoTaskMemFree( pszwInfIdLower );
} // Got the lower component id.
} // Got NIC's characteristics
ReleaseObj(pnccLower);
ReleaseObj(pnccUpper);
} // Got the upper and lower components.
}
TraceMsg( L"<--CMuxNotify INetCfgNotifyBinding::NotifyBindingPath(HRESULT = %x).\n",
S_OK );
return S_OK;
}
//----------------------------------------------------------------------------
// INetCfgComponentNotifyGlobal
//
// The following functions provide the INetCfgComponentNotifyGlobal interface.
//
//----------------------------------------------------------------------------
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::GetSupportedNotifications
//
// Purpose: Tell the system which notifications we are interested in
//
// Arguments:
// OUT pdwNotificationFlag: Pointer to NotificationFlag
//
// Returns: S_OK on success, otherwise an error code
//
// Notes:
//
STDMETHODIMP CMuxNotify::GetSupportedNotifications (
OUT DWORD* pdwNotificationFlag)
{
TraceMsg( L"-->CMuxNotify INetCfgNotifyGlobal::GetSupportedNotifications.\n" );
*pdwNotificationFlag = NCN_NET | NCN_NETTRANS | NCN_ADD | NCN_REMOVE |
NCN_BINDING_PATH | NCN_ENABLE | NCN_DISABLE;
TraceMsg( L"<--CMuxNotify INetCfgNotifyGlobal::GetSupportedNotifications(HRESULT = %x).\n",
S_OK );
return S_OK;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::SysQueryBindingPath
//
// Purpose: Enable or Disable a binding path.
//
// Arguments:
// IN dwChangeFlag: Type of binding change
// IN pncbp : Pointer to INetCfgBindingPath object
//
// Returns: S_OK on success, otherwise an error code
//
// Notes:
//
STDMETHODIMP CMuxNotify::SysQueryBindingPath (DWORD dwChangeFlag,
INetCfgBindingPath* pncbp)
{
INetCfgComponent *pnccLower;
INetCfgComponent *pnccUpper;
LPWSTR pszwInfIdLower;
LPWSTR pszwInfIdUpper;
DWORD dwCharcteristics;
HRESULT hr = S_OK;
TraceMsg( L"-->CMuxNotify INetCfgNotifyGlobal::SysQueryBindingPath.\n" );
DumpChangeFlag( dwChangeFlag );
DumpBindingPath( pncbp );
if ( dwChangeFlag & NCN_ENABLE ) {
//
// Get the upper and lower components.
//
hr = HrGetUpperAndLower( pncbp,
&pnccUpper,
&pnccLower );
if ( hr == S_OK ) {
hr = pnccLower->GetCharacteristics( &dwCharcteristics );
if ( hr == S_OK ) {
hr = pnccLower->GetId( &pszwInfIdLower );
if ( hr == S_OK ) {
hr = pnccUpper->GetId( &pszwInfIdUpper );
if ( hr == S_OK ) {
//
// We are interested only in bindings to physical
// ethernet adapters.
//
if ( dwCharcteristics & NCF_PHYSICAL ) {
#ifdef DISABLE_PROTOCOLS_TO_PHYSICAL
//
// If it not our protocol binding to the
// physical adapter then, disable the
// binding.
//
if (_wcsicmp( pszwInfIdUpper, c_szMuxProtocol ) ) {
TraceMsg( L" Disabling the binding between %s "
L"and %s.\n",
pszwInfIdUpper,
pszwInfIdLower );
hr = NETCFG_S_DISABLE_QUERY;
}
#endif
} // Physical Adapters.
else {
if (dwCharcteristics & NCF_VIRTUAL) {
// If the lower component is our miniport
// and the upper component is our protocol
// then also, disable the binding.
if ( !_wcsicmp(pszwInfIdLower, c_szMuxMiniport) &&
!_wcsicmp(pszwInfIdUpper, c_szMuxProtocol) ) {
TraceMsg( L" Disabling the binding between %s "
L"and %s.\n",
pszwInfIdUpper,
pszwInfIdLower );
hr = NETCFG_S_DISABLE_QUERY;
}
} // Virtual Adapters
}
CoTaskMemFree( pszwInfIdUpper );
} // Got the upper component id.
CoTaskMemFree( pszwInfIdLower );
} // Got the lower component id.
} // Got NIC's characteristics
ReleaseObj(pnccLower);
ReleaseObj(pnccUpper);
}
}
TraceMsg( L"<--CMuxNotify INetCfgNotifyGlobal::SysQueryBindingPath(HRESULT = %x).\n",
hr );
return hr;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::SysNotifyBindingPath
//
// Purpose: System tells us by calling this function which
// binding path has just been formed.
//
// Arguments:
// IN dwChangeFlag: Type of binding change
// IN pncbpItem : Pointer to INetCfgBindingPath object
//
// Returns: S_OK on success, otherwise an error code
//
// Notes:
//
STDMETHODIMP CMuxNotify::SysNotifyBindingPath (DWORD dwChangeFlag,
INetCfgBindingPath* pncbp)
{
TraceMsg( L"-->CMuxNotify INetCfgNotifyGlobal::SysNotifyBindingPath.\n" );
DumpChangeFlag( dwChangeFlag );
DumpBindingPath( pncbp );
TraceMsg( L"<--CMuxNotify INetCfgNotifyGlobal::SysNotifyBindingPath(HRESULT = %x).\n",
S_OK );
return S_OK;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::SysNotifyComponent
//
// Purpose: System tells us by calling this function which
// component has undergone a change (installed/removed)
//
// Arguments:
// IN dwChangeFlag: Type of system change
// IN pncc : Pointer to INetCfgComponent object
//
// Returns: S_OK on success, otherwise an error code
//
// Notes:
//
STDMETHODIMP CMuxNotify::SysNotifyComponent (DWORD dwChangeFlag,
INetCfgComponent* pncc)
{
TraceMsg( L"-->CMuxNotify INetCfgNotifyGlobal::SysNotifyComponent.\n" );
DumpChangeFlag( dwChangeFlag );
DumpComponent( pncc );
TraceMsg( L"<--CMuxNotify INetCfgNotifyGlobal::SysNotifyComponent(HRESULT = %x).\n",
S_OK );
return S_OK;
}
//----------------------------------------------------------------------------
// INetCfgComponentPropertyUi
//
// The following functions provide the INetCfgComponentPropertyUi interface.
//
//----------------------------------------------------------------------------
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::MergePropPages
//
// Purpose: Supply our property page to system.
//
// Arguments:
// OUT pdwDefPages : Pointer to num default pages
// OUT pahpspPrivate: Pointer to array of pages
// OUT pcPages : Pointer to num pages
// IN hwndParent : Handle of parent window
// IN szStartPage : Pointer to
//
// Returns: S_OK on success, otherwise an error code
//
// Notes:
//
STDMETHODIMP CMuxNotify::MergePropPages (IN OUT DWORD* pdwDefPages,
OUT LPBYTE* pahpspPrivate,
OUT UINT* pcPages,
IN HWND hwndParent,
OUT PCWSTR* szStartPage)
{
HRESULT hr = S_OK;
HPROPSHEETPAGE *ahpsp;;
INetLanConnectionUiInfo *pLanConnUiInfo;
TraceMsg(L"-->CMuxNotify INetCfgPropertyUi::MergePropPages\n");
//
// We don't want any default pages to be shown
//
*pdwDefPages = 0;
*pcPages = 0;
*pahpspPrivate = NULL;
if ( !m_pUnkContext ) {
return E_UNEXPECTED;
}
hr = m_pUnkContext->QueryInterface(
IID_INetLanConnectionUiInfo,
reinterpret_cast<PVOID *>(&pLanConnUiInfo));
if ( hr == S_OK ) {
ReleaseObj( pLanConnUiInfo );
ahpsp = (HPROPSHEETPAGE*)CoTaskMemAlloc( sizeof(HPROPSHEETPAGE) );
if (ahpsp) {
PROPSHEETPAGE psp = {0};
psp.dwSize = sizeof(PROPSHEETPAGE);
psp.dwFlags = PSP_DEFAULT;
psp.hInstance = _Module.GetModuleInstance();
psp.pszTemplate = MAKEINTRESOURCE(IDD_NOTIFY_GENERAL);
psp.pfnDlgProc = (DLGPROC)NotifyDialogProc;
psp.pfnCallback = NULL; (LPFNPSPCALLBACK)NotifyPropSheetPageProc;
psp.lParam = (LPARAM) this;
psp.pszHeaderTitle = NULL;
psp.pszHeaderSubTitle = NULL;
ahpsp[0] = ::CreatePropertySheetPage(&psp);
*pcPages = 1;
*pahpspPrivate = (LPBYTE)ahpsp;
}
else {
hr = E_OUTOFMEMORY;
}
}
TraceMsg(L"<--CMuxNotify INetCfgPropertyUi::MergePropPages(HRESULT = %x).\n",
hr );
return hr;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::ValidateProperties
//
// Purpose: Validate changes to property page.
//
// Arguments:
// IN hwndSheet: Window handle of property sheet
//
// Returns: S_OK on success, otherwise an error code
//
// Notes:
//
STDMETHODIMP CMuxNotify::ValidateProperties (HWND hwndSheet)
{
TraceMsg( L"-->CMuxNotify INetCfgPropertyUi::ValidateProperties\n" );
TraceMsg(L"<--CMuxNotify INetCfgPropertyUi::ValidateProperties(HRESULT = %x).\n",
S_OK );
return S_OK;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::CancelProperties
//
// Purpose: Cancel changes to property page
//
// Arguments: None
//
// Returns: S_OK on success, otherwise an error code
//
// Notes:
//
STDMETHODIMP CMuxNotify::CancelProperties (VOID)
{
TraceMsg(L"-->CMuxNotify INetCfgPropertyUi::CancelProperties\n");
TraceMsg(L"<--CMuxNotify INetCfgPropertyUi::CancelProperties(HRESULT = %x).\n",
S_OK );
return S_OK;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::ApplyProperties
//
// Purpose: Apply value of controls on property page
// to internal memory structure
//
// Arguments: None
//
// Returns: S_OK on success, otherwise an error code
//
// Notes:
//
STDMETHODIMP CMuxNotify::ApplyProperties (VOID)
{
INetLanConnectionUiInfo *pLanConnUiInfo;
CMuxPhysicalAdapter *pAdapter;
GUID guidAdapter;
INetCfgComponent *pncc;
HRESULT hr = S_OK;
TraceMsg(L"-->CMuxNotify INetCfgPropertyUi::ApplyProperties\n");
if ( m_pUnkContext ) {
hr = m_pUnkContext->QueryInterface(
IID_INetLanConnectionUiInfo,
reinterpret_cast<PVOID *>(&pLanConnUiInfo));
if ( hr == S_OK ) {
hr = pLanConnUiInfo->GetDeviceGuid( &guidAdapter );
if ( hr == S_OK ) {
hr = m_AdaptersList.FindByKey( guidAdapter,
&pAdapter );
if ( hr == S_OK ) {
switch( m_eApplyAction ) {
case eActPropertyUIAdd:
hr = HrAddMiniport( pAdapter,
&guidAdapter );
break;
case eActPropertyUIRemove:
hr = HrRemoveMiniport( pAdapter,
&guidAdapter );
break;
}
}
}
ReleaseObj( pLanConnUiInfo );
}
}
TraceMsg(L"<--CMuxNotify INetCfgPropertyUi::ApplyProperties(HRESULT = %x).\n",
hr );
return hr;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::QueryPropertyUi
//
// Purpose: System is asking if we support property pages.
//
// Arguments:
// IN pUnk: Pointer to IUnknown.
//
// Returns: S_OK on success, otherwise an error code
//
// Notes: We display property pages only in the context of
// a LAN connection.
//
STDMETHODIMP CMuxNotify::QueryPropertyUi (IUnknown * pUnk)
{
INetLanConnectionUiInfo *pLanConnUiInfo;
HRESULT hr=S_FALSE;
TraceMsg(L"-->CMuxNotify INetCfgPropertyUi::QueryPropertyUi\n");
#ifndef PASSTHRU_NOTIFY
if ( pUnk ) {
hr = pUnk->QueryInterface(
IID_INetLanConnectionUiInfo,
reinterpret_cast<PVOID *>(&pLanConnUiInfo));
ReleaseObj( pLanConnUiInfo );
}
#endif
TraceMsg(L"<--CMuxNotify INetCfgPropertyUi::QueryPropertyUi(HRESULT = %x).\n",
hr );
return hr;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::SetContext
//
// Purpose: Save the LAN connection context.
//
// Arguments:
// IN pUnk: Pointer to IUnknown.
//
// Returns: S_OK on success, otherwise an error code
//
// Notes: It is also called to release the current LAN connection context.
//
STDMETHODIMP CMuxNotify::SetContext (IUnknown * pUnk)
{
TraceMsg(L"-->CMuxNotify INetCfgPropertyUi::SetContext\n");
//
// Release previous context, if any
//
ReleaseObj( m_pUnkContext );
m_pUnkContext = NULL;
if ( pUnk ) {
m_pUnkContext = pUnk;
m_pUnkContext->AddRef();
}
TraceMsg(L"<--CMuxNotify INetCfgPropertyUi::SetContext(HRESULT = %x).\n",
S_OK );
return S_OK;
}
//----------------------------------------------------------------------------
//
// Function: CMuxNotify::HrLoadAdapterConfiguration
//
// Purpose: This loads the Miniport and adapters that have already been
// installed into our own data structures
//
// Arguments: None.
//
// Returns: S_OK, or an error.
//
//
// Notes:
//
HRESULT CMuxNotify::HrLoadAdapterConfiguration (VOID)
{
HKEY hkeyAdapterList;
WCHAR szAdapterGuid[MAX_PATH+1];
DWORD dwDisp;
CMuxPhysicalAdapter *pAdapter;
GUID guidAdapter;
DWORD dwIndex;
LONG lResult;
TraceMsg( L"-->CMuxNotify::HrLoadAdapterConfiguration.\n" );
lResult = RegCreateKeyExW( HKEY_LOCAL_MACHINE,
c_szAdapterList,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hkeyAdapterList,
&dwDisp);
if ( lResult == ERROR_SUCCESS ) {
//
// If dwDisp indicates that a new key is created then, we know there
// is no adapter currently listed underneath and we simply
// return, otherwise, we enumerate the subkeys, each one representing an
// adapter.
//
if ( dwDisp != REG_CREATED_NEW_KEY ) {
lResult = RegEnumKeyW( hkeyAdapterList,
0,
szAdapterGuid,
MAX_PATH+1 );
for (dwIndex=1; lResult == ERROR_SUCCESS; ++dwIndex) {
TraceMsg( L" Loading configuration for adapter %s...\n",
szAdapterGuid );
//
// Subkeys are actually a guid/bindname of the adapters.
//
CLSIDFromString( szAdapterGuid,
&guidAdapter );
//
// Create an instance representing the adapter.
//
pAdapter = new CMuxPhysicalAdapter( m_pnc,
&guidAdapter );
if ( pAdapter ) {
//
// Load any adapter specific configuration.
//
pAdapter->LoadConfiguration();
//
// Save the adapter instance in a list.
//
m_AdaptersList.Insert( pAdapter,
guidAdapter );
//
// Get next subkey.
//
lResult = RegEnumKeyW( hkeyAdapterList,
dwIndex,
szAdapterGuid,
MAX_PATH+1 );
}
else {
lResult = ERROR_NOT_ENOUGH_MEMORY;
}
}
//
// RegEnumKeyW may have returned error when there are no more
// subkeys to read.
//
lResult = ERROR_SUCCESS;
}
RegCloseKey( hkeyAdapterList );
}
TraceMsg( L"<--CMuxNotify::HrLoadAdapterConfiguration(HRESULT = %x).\n",
HRESULT_FROM_WIN32(lResult) );
return HRESULT_FROM_WIN32(lResult);
}
//----------------------------------------------------------------------------
//
// Function: CMuxNotify::HrGetUpperAndLower
//
// Purpose: Get the upper and lower component of the first interface
// of a binding path.
//
// Arguments:
// IN pncbp : Binding path.
// OUT ppnccUpper: Upper component.
// OUT ppnccLower: Lower component.
//
// Returns: S_OK, or an error.
//
//
// Notes:
//
HRESULT CMuxNotify::HrGetUpperAndLower (INetCfgBindingPath* pncbp,
INetCfgComponent **ppnccUpper,
INetCfgComponent **ppnccLower)
{
IEnumNetCfgBindingInterface* pencbi;
INetCfgBindingInterface* pncbi;
ULONG ulCount;
HRESULT hr;
TraceMsg( L"-->CMuxNotify::HrGetUpperAndLowerComponent.\n" );
*ppnccUpper = NULL;
*ppnccLower = NULL;
hr = pncbp->EnumBindingInterfaces(&pencbi);
if (S_OK == hr) {
//
// get the first binding interface
//
hr = pencbi->Next(1, &pncbi, &ulCount);
if ( hr == S_OK ) {
hr = pncbi->GetUpperComponent( ppnccUpper );
if ( hr == S_OK ) {
hr = pncbi->GetLowerComponent ( ppnccLower );
}
else {
ReleaseObj( *ppnccUpper );
}
ReleaseObj( pncbi );
}
ReleaseObj( pencbi );
}
TraceMsg( L"<--CMuxNotify::HrGetUpperAndLowerComponent(HRESULT = %x).\n",
hr );
return hr;
}
//----------------------------------------------------------------------------
//
// Function: CMuxNotify::HrAddAdapter
//
// Purpose: Create an instance representing the physical adapter and install
// a virtual miniport.
//
// Arguments:
// IN pnccAdapter: Pointer to the physical adapter.
//
// Returns: S_OK, or an error.
//
//
// Notes:
//
HRESULT CMuxNotify::HrAddAdapter (INetCfgComponent *pnccAdapter)
{
GUID guidAdapter;
CMuxPhysicalAdapter *pAdapter;
HRESULT hr;
TraceMsg( L"-->CMuxNotify::HrAddAdapter.\n" );
hr = pnccAdapter->GetInstanceGuid( &guidAdapter );
if ( hr == S_OK ) {
pAdapter = new CMuxPhysicalAdapter( m_pnc,
&guidAdapter );
if ( pAdapter ) {
hr = HrAddMiniport( pAdapter,
&guidAdapter );
if ( hr == S_OK ) {
m_AdaptersToAdd.Insert( pAdapter,
guidAdapter );
}
else {
delete pAdapter;
}
}
else {
hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
}
}
TraceMsg( L"<--CMuxNotify::HrAddAdapter(HRESULT = %x).\n",
hr );
return hr;
}
//----------------------------------------------------------------------------
//
// Function: CMuxNotify::HrRemoveAdapter
//
// Purpose: Deletes the instance representing the physical adapter
// and uninstalls all the virtual miniports.
//
// Arguments:
// IN pnccAdapter: Pointer to the physical adapter.
//
// Returns: S_OK, or an error.
//
//
// Notes: This function is called when the adapter or the protocol
// is being uninstalled.
//
HRESULT CMuxNotify::HrRemoveAdapter (INetCfgComponent *pnccAdapter)
{
GUID guidAdapter;
CMuxPhysicalAdapter *pAdapter;
HRESULT hr;
TraceMsg( L"-->CMuxNotify::HrRemoveAdapter.\n" );
hr = pnccAdapter->GetInstanceGuid( &guidAdapter );
if ( hr == S_OK ) {
hr = m_AdaptersList.RemoveByKey( guidAdapter,
&pAdapter );
if ( hr == S_OK ) {
m_AdaptersToRemove.Insert( pAdapter,
guidAdapter );
hr = pAdapter->Remove();
#ifdef DISABLE_PROTOCOLS_TO_PHYSICAL
//
// Restore the bindings of other protocols to the physical
// adapter.
//
EnableBindings( pnccAdapter,
TRUE );
#endif
}
}
TraceMsg( L"<--CMuxNotify::HrRemoveAdapter(HRESULT = %x).\n",
hr );
return hr;
}
//----------------------------------------------------------------------------
//
// Function: CMuxNotify::HrAddMiniport
//
// Purpose: Installs a virtual miniport.
//
// Arguments:
// IN pAdapter : Pointer to the physical adapter class instance.
// IN pguidAdapter: Pointer to the GUID of the adapter.
//
// Returns: S_OK, or an error.
//
//
// Notes:
//
HRESULT CMuxNotify::HrAddMiniport (CMuxPhysicalAdapter *pAdapter,
GUID *pguidAdapter)
{
CMuxVirtualMiniport *pMiniport;
INetCfgComponent *pnccAdapter;
HRESULT hr;
TraceMsg( L"-->CMuxNotify::HrAddMiniport.\n" );
pMiniport = new CMuxVirtualMiniport( m_pnc,
NULL,
pguidAdapter );
if ( pMiniport ) {
hr = pMiniport->Install();
if ( hr == S_OK ) {
hr = pAdapter->AddMiniport( pMiniport );
if ( hr != S_OK ) {
pMiniport->DeInstall();
delete pMiniport;
}
}
}
else {
hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
}
#ifdef DISABLE_PROTOCOLS_TO_PHYSICAL
if ( hr == S_OK ) {
//
// If this is the first virtual miniport then, disable the bindings
// of other protocols to the physical adapter.
//
if ( pAdapter->MiniportCount() == 0 ) {
hr = HrFindInstance( m_pnc,
*pguidAdapter,
&pnccAdapter );
if ( hr == S_OK ) {
EnableBindings( pnccAdapter,
FALSE );
ReleaseObj( pnccAdapter );
}
}
}
#endif
TraceMsg( L"<--CMuxNotify::HrAddMiniport(HRESULT = %x).\n",
hr );
return hr;
}
//----------------------------------------------------------------------------
//
// Function: CMuxNotify::HrRemoveMiniport
//
// Purpose: Uninstalls a virtual miniport.
//
// Arguments:
// IN pAdapter : Pointer to the physical adapter class instance.
// IN pguidAdapter: Pointer to the GUID of the adapter.
//
// Returns: S_OK, or an error.
//
//
// Notes:
//
HRESULT CMuxNotify::HrRemoveMiniport (CMuxPhysicalAdapter *pAdapter,
GUID *pguidAdapter)
{
INetCfgComponent *pnccAdapter;
HRESULT hr;
TraceMsg( L"-->CMuxNotify::HrRemoveMiniport.\n" );
hr = pAdapter->RemoveMiniport( NULL );
#ifdef DISABLE_PROTOCOLS_TO_PHYSICAL
if ( hr == S_OK ) {
//
// If this was the last miniport that was removed then, restore the
// bindings of other protocols to the physical adapter.
//
if ( pAdapter->AllMiniportsRemoved() ) {
hr = HrFindInstance( m_pnc,
*pguidAdapter,
&pnccAdapter );
if ( hr == S_OK ) {
EnableBindings( pnccAdapter,
TRUE );
ReleaseObj( pnccAdapter );
}
}
}
#endif
TraceMsg( L"<--CMuxNotify::HrRemoveMiniport(HRESULT = %x).\n",
hr );
return hr;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::OnInitDialog
//
// Purpose: Initialize controls
//
// Arguments:
// IN hWnd: Window handle to the property page.
//
// Returns: TRUE.
//
// Notes:
//
LRESULT CMuxNotify::OnInitDialog (IN HWND hWndPage)
{
m_eApplyAction = eActUnknown;
::SendMessage(GetDlgItem(hWndPage, IDC_ADD), BM_SETCHECK, BST_CHECKED, 0);
::SendMessage(GetDlgItem(hWndPage, IDC_REMOVE), BM_SETCHECK, BST_UNCHECKED, 0);
return TRUE;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::OnOk
//
// Purpose: Do actions when OK is pressed
//
// Arguments:
// IN hWnd: Window handle to the property page.
//
// Returns: PSNRET_NOERROR
//
// Notes:
//
LRESULT CMuxNotify::OnOk (IN HWND hWndPage)
{
TraceMsg(L"-->CMuxNotify::OnOk\n");
if ( ::SendMessage(GetDlgItem(hWndPage, IDC_ADD),
BM_GETCHECK, 0, 0) == BST_CHECKED ) {
m_eApplyAction = eActPropertyUIAdd;
}
else {
m_eApplyAction = eActPropertyUIRemove;
}
//
// Set the property sheet changed flag if any of our controls
// get changed. This is important so that we get called to
// apply our property changes.
//
PropSheet_Changed( GetParent(hWndPage), hWndPage);
TraceMsg(L"<--CMuxNotify::OnOk(Action = %s).\n",
(m_eApplyAction == eActPropertyUIAdd) ? L"Add" : L"Remove" );
return PSNRET_NOERROR;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::OnCancel
//
// Purpose: Do actions when CANCEL is pressed
//
// Arguments:
// IN hWnd: Window handle to the property page.
//
// Returns: FALSE
//
// Notes:
//
LRESULT CMuxNotify::OnCancel (IN HWND hWndPage)
{
TraceMsg(L"-->CMuxNotify::OnCancel\n");
m_eApplyAction = eActUnknown;
TraceMsg(L"<--CMuxNotify::OnCancel\n");
return FALSE;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotifyDialogProc
//
// Purpose: Dialog proc
//
// Arguments:
// IN hWnd : See win32 documentation.
// IN uMsg : See win32 documentation.
// IN wParam: See win32 documentation.
// IN lParam: See win32 documentation.
//
// Returns: See win32 documentation.
//
// Notes:
//
LRESULT CALLBACK NotifyDialogProc (HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
CMuxNotify *psf;
LRESULT lRes=FALSE;
if ( uMsg != WM_INITDIALOG ) {
psf = (CMuxNotify *)::GetWindowLongPtr( hWnd,
DWLP_USER );
// Until we get WM_INITDIALOG, just return FALSE
if ( !psf ) {
return lRes;
}
}
switch( uMsg ) {
case WM_INITDIALOG:
{
PROPSHEETPAGE* ppsp;
ppsp = (PROPSHEETPAGE *)lParam;
psf = (CMuxNotify *)ppsp->lParam;
SetWindowLongPtr( hWnd,
DWLP_USER,
(LONG_PTR)psf);
lRes = psf->OnInitDialog( hWnd );
}
break;
case WM_COMMAND:
break;
case WM_NOTIFY:
{
LPNMHDR pnmh = (LPNMHDR)lParam;
switch (pnmh->code) {
case PSN_KILLACTIVE:
//
// ok to loose focus.
//
SetWindowLongPtr( hWnd, DWLP_MSGRESULT, FALSE);
lRes = TRUE;
break;
case PSN_APPLY:
psf = (CMuxNotify *)::GetWindowLongPtr( hWnd, DWLP_USER);
lRes = psf->OnOk( hWnd );
SetWindowLongPtr( hWnd, DWLP_MSGRESULT, lRes);
lRes = TRUE;
break;
case PSN_RESET:
psf = (CMuxNotify *)::GetWindowLongPtr( hWnd, DWLP_USER);
psf->OnCancel( hWnd );
}
}
}
return lRes;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotifyPropSheetPageProc
//
// Purpose: Prop sheet proc
//
// Arguments:
// IN hWnd: See win32 documentation
// IN uMsg: See win32 documentation
// IN ppsp: See win32 documentation
//
// Returns: See win32 documentation
//
// Notes:
//
UINT CALLBACK NotifyPropSheetPageProc(HWND hWnd,
UINT uMsg,
LPPROPSHEETPAGE ppsp)
{
return TRUE;
}
#ifdef DISABLE_PROTOCOLS_TO_PHYSICAL
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::EnableBindings
//
// Purpose: Enable/Disable the bindings of other protocols to
// the physical adapter.
//
// Arguments:
// IN pnccAdapter: Pointer to the physical adapter.
// IN bEnable: TRUE/FALSE to enable/disable respectively.
//
// Returns: None.
//
// Notes:
//
VOID CMuxNotify::EnableBindings (INetCfgComponent *pnccAdapter,
BOOL bEnable)
{
IEnumNetCfgBindingPath *pencbp;
INetCfgBindingPath *pncbp;
HRESULT hr;
TraceMsg( L"-->CMuxNotify::EnableBindings.\n" );
//
// Get the binding path enumerator.
//
hr = HrGetBindingPathEnum( pnccAdapter,
EBP_ABOVE,
&pencbp );
if ( hr == S_OK ) {
hr = HrGetBindingPath( pencbp,
&pncbp );
//
// Traverse each binding path.
//
while( hr == S_OK ) {
//
// If our protocol does exist in the binding path then,
// disable it.
//
if ( !IfExistMux(pncbp) ) {
pncbp->Enable( bEnable );
}
ReleaseObj( pncbp );
hr = HrGetBindingPath( pencbp,
&pncbp );
}
ReleaseObj( pencbp );
}
else {
TraceMsg( L" Couldn't get the binding path enumerator, "
L"bindings will not be %s.\n",
bEnable ? L"enabled" : L"disabled" );
}
TraceMsg( L"<--CMuxNotify::EnableBindings.\n" );
return;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::IfExistMux
//
// Purpose: Determine if a given binding path contains our protocol.
//
// Arguments:
// IN pncbp: Pointer to the binding path.
//
// Returns: TRUE if our protocol exists, otherwise FALSE.
//
// Notes:
//
BOOL CMuxNotify::IfExistMux (INetCfgBindingPath *pncbp)
{
IEnumNetCfgBindingInterface *pencbi;
INetCfgBindingInterface *pncbi;
INetCfgComponent *pnccUpper;
LPWSTR lpszIdUpper;
HRESULT hr;
BOOL bExist = FALSE;
TraceMsg( L"-->CMuxNotify::IfExistMux.\n" );
//
// Get the binding interface enumerator.
//
hr = HrGetBindingInterfaceEnum( pncbp,
&pencbi );
if ( hr == S_OK ) {
//
// Traverse each binding interface.
//
hr = HrGetBindingInterface( pencbi,
&pncbi );
while( !bExist && (hr == S_OK) ) {
//
// Is the upper component our protocol?
//
hr = pncbi->GetUpperComponent( &pnccUpper );
if ( hr == S_OK ) {
hr = pnccUpper->GetId( &lpszIdUpper );
if ( hr == S_OK ) {
bExist = !_wcsicmp( lpszIdUpper, c_szMuxProtocol );
CoTaskMemFree( lpszIdUpper );
}
else {
TraceMsg( L" Failed to get the upper component of the interface.\n" );
}
ReleaseObj( pnccUpper );
}
else {
TraceMsg( L" Failed to get the upper component of the interface.\n" );
}
ReleaseObj( pncbi );
if ( !bExist ) {
hr = HrGetBindingInterface( pencbi,
&pncbi );
}
}
ReleaseObj( pencbi );
}
else {
TraceMsg( L" Couldn't get the binding interface enumerator.\n" );
}
TraceMsg( L"<--CMuxNotify::IfExistMux(BOOL = %x).\n",
bExist );
return bExist;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::HrGetBindingPathEnum
//
// Purpose: Returns the binding path enumerator.
//
// Arguments:
// IN pnccAdapter : Pointer to the physical adapter.
// IN dwBindingType: Type of binding path enumerator.
// OUT ppencbp : Pointer to the binding path enumerator.
//
// Returns: S_OK on success, otherwise an error code.
//
// Notes:
//
HRESULT CMuxNotify::HrGetBindingPathEnum (
INetCfgComponent *pnccAdapter,
DWORD dwBindingType,
IEnumNetCfgBindingPath **ppencbp)
{
INetCfgComponentBindings *pnccb = NULL;
HRESULT hr;
*ppencbp = NULL;
hr = pnccAdapter->QueryInterface( IID_INetCfgComponentBindings,
(PVOID *)&pnccb );
if ( hr == S_OK ) {
hr = pnccb->EnumBindingPaths( dwBindingType,
ppencbp );
ReleaseObj( pnccb );
}
return hr;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::HrGetBindingPath
//
// Purpose: Returns a binding path.
//
// Arguments:
// IN pencbp : Pointer to the binding path enumerator.
// OUT ppncbp : Pointer to the binding path.
//
// Returns: S_OK on success, otherwise an error code.
//
// Notes:
//
HRESULT CMuxNotify::HrGetBindingPath (IEnumNetCfgBindingPath *pencbp,
INetCfgBindingPath **ppncbp)
{
ULONG ulCount;
HRESULT hr;
*ppncbp = NULL;
hr = pencbp->Next( 1,
ppncbp,
&ulCount );
return hr;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::HrGetBindingInterfaceEnum
//
// Purpose: Returns the binding interface enumerator.
//
// Arguments:
// IN pncbp : Pointer to the binding path.
// OUT ppencbi: Pointer to the binding path enumerator.
//
// Returns: S_OK on success, otherwise an error code.
//
// Notes:
//
HRESULT CMuxNotify::HrGetBindingInterfaceEnum (
INetCfgBindingPath *pncbp,
IEnumNetCfgBindingInterface **ppencbi)
{
HRESULT hr;
*ppencbi = NULL;
hr = pncbp->EnumBindingInterfaces( ppencbi );
return hr;
}
// ----------------------------------------------------------------------
//
// Function: CMuxNotify::HrGetBindingInterface
//
// Purpose: Returns a binding interface.
//
// Arguments:
// IN pencbi : Pointer to the binding interface enumerator.
// OUT ppncbi : Pointer to the binding interface.
//
// Returns: S_OK on success, otherwise an error code.
//
// Notes:
//
HRESULT CMuxNotify::HrGetBindingInterface (
IEnumNetCfgBindingInterface *pencbi,
INetCfgBindingInterface **ppncbi)
{
ULONG ulCount;
HRESULT hr;
*ppncbi = NULL;
hr = pencbi->Next( 1,
ppncbi,
&ulCount );
return hr;
}
#endif