home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2006 June / PCpro_2006_06.ISO / files / mstools / MSRMesh-VirtualWIFI.MSI / notify.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2005-06-24  |  58.6 KB  |  2,178 lines

  1. /*
  2.  * Author   : Ranveer Chandra
  3.  * Directory: VirtualWiFi_Root\notifyob
  4.  * File Name: notify.cpp
  5.  * Purpose  : VirtualWiFi notify object code.
  6.  */
  7.  
  8. #include "notify.h"
  9.  
  10. HRESULT HrCopyMiniportInf (VOID);
  11.  
  12. //----------------------------------------------------------------------------
  13. //
  14. // Function:  CMuxNotify::CMuxNotify
  15. //
  16. // Purpose:   Constructor for CMuxNotify
  17. //
  18. // Arguments: None
  19. //
  20. // Returns:   None
  21. //
  22. // Notes:
  23. //
  24.  
  25. CMuxNotify::CMuxNotify (VOID) : m_pncc (NULL),
  26.                                 m_pnc(NULL),
  27.                                 m_eApplyAction(eActUnknown),
  28.                                 m_pUnkContext(NULL)
  29. {
  30.     TraceMsg( L"-->CMuxNotify::CMuxNotify(Constructor).\n" );
  31.  
  32.     TraceMsg( L"<--CMuxNotify::CMuxNotify(Constructor).\n" );
  33. }
  34.  
  35.  
  36. // ----------------------------------------------------------------------
  37. //
  38. // Function:  CMuxNotify::~CMuxNotify
  39. //
  40. // Purpose:   Destructor for class CMuxNotify
  41. //
  42. // Arguments: None
  43. //
  44. // Returns:   None
  45. //
  46. // Notes:
  47. //
  48. CMuxNotify::~CMuxNotify (VOID)
  49. {
  50.     CMuxPhysicalAdapter *pAdapter;
  51.     DWORD dwAdapterCount;
  52.     DWORD i;
  53.  
  54.     TraceMsg( L"-->CMuxNotify::~CMuxNotify(Destructor).\n" );
  55.  
  56.     // release interfaces if acquired
  57.  
  58.     ReleaseObj( m_pncc );
  59.     ReleaseObj( m_pnc );
  60.     ReleaseObj( m_pUnkContext );
  61.  
  62.     dwAdapterCount = m_AdaptersList.ListCount();
  63.  
  64.     for (i=0; i < dwAdapterCount; ++i) {
  65.  
  66.         m_AdaptersList.Remove( &pAdapter );
  67.  
  68.         delete pAdapter;
  69.     }
  70.  
  71.     dwAdapterCount = m_AdaptersToRemove.ListCount();
  72.  
  73.     for (i=0; i < dwAdapterCount; ++i) {
  74.  
  75.         m_AdaptersToRemove.Remove( &pAdapter );
  76.  
  77.         delete pAdapter;
  78.     }
  79.  
  80.     dwAdapterCount = m_AdaptersToAdd.ListCount();
  81.  
  82.     for (i=0; i < dwAdapterCount; ++i) {
  83.  
  84.         m_AdaptersToAdd.Remove( &pAdapter );
  85.  
  86.         delete pAdapter;
  87.     }
  88.  
  89.     TraceMsg( L"<--CMuxNotify::~CMuxNotify(Destructor).\n" );
  90. }
  91.  
  92. //
  93. //---------------------- NOTIFY OBJECT FUNCTIONS -----------------------------
  94. //
  95.  
  96. //----------------------------------------------------------------------------
  97. // INetCfgComponentControl                                           
  98. //                                                                       
  99. // The following functions provide the INetCfgComponentControl interface.
  100. //                                                                       
  101. //----------------------------------------------------------------------------
  102.  
  103. //
  104. // Function:  CMuxNotify::Initialize
  105. //
  106. // Purpose:   Initialize the notify object
  107. //
  108. // Arguments:
  109. //           IN pnccItem   :  Pointer to INetCfgComponent object
  110. //           IN pnc        :  Pointer to INetCfg object
  111. //           IN fInstalling:  TRUE if we are being installed
  112. //
  113. // Returns:
  114. //
  115. // Notes:
  116. //
  117.  
  118. STDMETHODIMP CMuxNotify::Initialize (INetCfgComponent* pncc,
  119.                                      INetCfg* pnc, 
  120.                                      BOOL fInstalling)
  121. {
  122.     HRESULT hr = S_OK;
  123.  
  124.     TraceMsg( L"-->CMuxNotify INetCfgControl::Initialize.\n" );
  125.  
  126.  
  127.     // Save INetCfg & INetCfgComponent and add a refcount
  128.  
  129.     m_pncc = pncc;
  130.     m_pnc = pnc;
  131.  
  132.     if (m_pncc) {
  133.  
  134.         m_pncc->AddRef();
  135.     }
  136.  
  137.     if (m_pnc) {
  138.  
  139.         m_pnc->AddRef();
  140.     }
  141.  
  142.  
  143.     //
  144.     // If this not an installation, then we need to 
  145.     // initialize all of our data and classes
  146.     //
  147.  
  148.     if ( !fInstalling ) {
  149.  
  150.         hr = HrLoadAdapterConfiguration();
  151.     }else  {
  152.         OSVERSIONINFO osvi;
  153.  
  154.         ZeroMemory( &osvi,
  155.                     sizeof(OSVERSIONINFO) );
  156.         
  157.         osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  158.  
  159.         if ( GetVersionEx(&osvi) ) 
  160.         {
  161.             if ( (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) && 
  162.                  (osvi.dwMajorVersion == 5) &&
  163.                  (osvi.dwMinorVersion == 0) )
  164.             {
  165.                 // On Windows 2000, copy the miniport inf file to %windir%\inf.
  166.  
  167.                 TraceMsg(L"    Copying miniport inf to system inf directory...\n");
  168.                 HrCopyMiniportInf();
  169.             }
  170.             else
  171.             {
  172.                 TraceMsg(L"    Skipping copying miniport inf to system inf directory...\n");
  173.             }
  174.         }
  175.     }    
  176.     TraceMsg( L"<--CMuxNotify INetCfgControl::Initialize(HRESULT = %x).\n",
  177.            hr );
  178.  
  179.     return hr;
  180. }
  181.  
  182. // ----------------------------------------------------------------------
  183. //
  184. // Function:  CMuxNotify::CancelChanges
  185. //
  186. // Purpose:   Cancel any changes made to internal data
  187. //
  188. // Arguments: None
  189. //
  190. // Returns:   S_OK on success, otherwise an error code
  191. //
  192. // Notes:
  193. //
  194.  
  195. STDMETHODIMP CMuxNotify::CancelChanges (VOID)
  196. {
  197.     TraceMsg( L"-->CMuxNotify INetCfgControl::CancelChanges.\n" );
  198.  
  199.  
  200.     TraceMsg( L"<--CMuxNotify INetCfgControl::CancelChanges(HRESULT = %x).\n",
  201.               S_OK );
  202.  
  203.     return S_OK;
  204. }
  205.  
  206. // ----------------------------------------------------------------------
  207. //
  208. // Function:  CMuxNotify::ApplyRegistryChanges
  209. //
  210. // Purpose:   Apply changes.
  211. //
  212. // Arguments: None
  213. //
  214. // Returns:   S_OK.
  215. //
  216. // Notes:     We can make changes to registry etc. here.
  217.  
  218. STDMETHODIMP CMuxNotify::ApplyRegistryChanges(VOID)
  219. {
  220.     CMuxPhysicalAdapter *pAdapter = NULL;
  221.     GUID                   guidAdapter;
  222.     DWORD                  dwAdapterCount;
  223.     DWORD                  i;
  224.  
  225.     TraceMsg( L"-->CMuxNotify INetCfgControl::ApplyRegistryChanges.\n" );
  226.  
  227.     //
  228.     // Make registry changes for the adapters added.
  229.     //
  230.  
  231.     dwAdapterCount = m_AdaptersToAdd.ListCount();
  232.  
  233.     TraceMsg( L"   Adding %d new adapters.\n",
  234.               dwAdapterCount );
  235.  
  236.     for (i=0; i < dwAdapterCount; ++i) {
  237.  
  238.         m_AdaptersToAdd.Find( i,
  239.                               &pAdapter );
  240.    
  241.         pAdapter->ApplyRegistryChanges( eActAdd );
  242.  
  243.     }
  244.  
  245.     //
  246.     // Make registry changes for the adapters uninstalled.
  247.     //
  248.  
  249.     dwAdapterCount = m_AdaptersToRemove.ListCount();
  250.  
  251.     TraceMsg( L"   Removing %d adapters.\n",
  252.               dwAdapterCount );
  253.  
  254.     for (i=0; i < dwAdapterCount; ++i) {
  255.  
  256.         m_AdaptersToRemove.Find( i,
  257.                                  &pAdapter );
  258.            
  259.         pAdapter->ApplyRegistryChanges( eActRemove );
  260.     }
  261.  
  262.     //
  263.     // Make registry changes for the miniports added/removed
  264.     // through the property pages.
  265.     //
  266.  
  267.     dwAdapterCount = m_AdaptersList.ListCount();
  268.  
  269.     for (i=0; i < dwAdapterCount; ++i) {
  270.  
  271.         m_AdaptersList.Find( i,
  272.                              &pAdapter );
  273.  
  274.         pAdapter->ApplyRegistryChanges( eActUpdate );
  275.     }
  276.  
  277.     TraceMsg( L"<--CMuxNotify INetCfgControl::ApplyRegistryChanges(HRESULT = %x).\n",
  278.               S_OK );
  279.  
  280.     return S_OK;
  281. }
  282.  
  283. // ----------------------------------------------------------------------
  284. //
  285. // Function:  CMuxNotify::ApplyPnpChanges
  286. //
  287. // Purpose:   Apply changes.
  288. //
  289. // Arguments:
  290. //            IN pfCallback: PnPConfigCallback interface.
  291. //
  292. // Returns:   S_OK.
  293. //
  294. // Notes:     
  295.  
  296. STDMETHODIMP CMuxNotify::ApplyPnpChanges (
  297.                                        INetCfgPnpReconfigCallback* pfCallback)
  298. {
  299.     CMuxPhysicalAdapter *pAdapter = NULL;
  300.     GUID                   guidAdapter;
  301.     DWORD                  dwAdapterCount;
  302.     DWORD                  i;
  303.  
  304.     TraceMsg( L"-->CMuxNotify INetCfgControl::ApplyPnpChanges.\n" );
  305.  
  306.     //
  307.     // Apply PnP changes for the adapters added.
  308.     //
  309.  
  310.     dwAdapterCount = m_AdaptersToAdd.ListCount();
  311.  
  312.     TraceMsg( L"   Applying PnP changes when %d adapters added.\n",
  313.             dwAdapterCount );
  314.  
  315.     for (i=0; i < dwAdapterCount; ++i) {
  316.  
  317.         m_AdaptersToAdd.Remove( &pAdapter );
  318.  
  319.         pAdapter->ApplyPnpChanges( pfCallback,
  320.                                 eActAdd );
  321.  
  322.         pAdapter->GetAdapterGUID( &guidAdapter );
  323.  
  324.         m_AdaptersList.Insert( pAdapter,
  325.                             guidAdapter );
  326.     }
  327.  
  328.     //
  329.     // Apply PnP changes for the adapters uninstalled.
  330.     //
  331.  
  332.     dwAdapterCount = m_AdaptersToRemove.ListCount();
  333.  
  334.     TraceMsg( L"   Applying PnP changes when %d adapters removed.\n",
  335.             dwAdapterCount );
  336.  
  337.     for (i=0; i < dwAdapterCount; ++i) {
  338.  
  339.         m_AdaptersToRemove.Remove( &pAdapter );
  340.  
  341.         pAdapter->ApplyPnpChanges( pfCallback,
  342.                             eActRemove );
  343.  
  344.         delete pAdapter;
  345.     }
  346.  
  347.     //
  348.     // Apply PnP changes for the miniports added/removed through
  349.     // the property pages.
  350.     //
  351.  
  352.     dwAdapterCount = m_AdaptersList.ListCount();
  353.  
  354.     for (i=0; i < dwAdapterCount; ++i) {
  355.  
  356.         m_AdaptersList.Find( i,
  357.                           &pAdapter );
  358.  
  359.         pAdapter->ApplyPnpChanges( pfCallback,
  360.                                 eActUpdate );
  361.     }
  362.  
  363.     TraceMsg( L"<--CMuxNotify INetCfgControl::ApplyPnpChanges(HRESULT = %x).\n",
  364.             S_OK );
  365.  
  366.     return S_OK;
  367. }
  368.  
  369.  
  370. //----------------------------------------------------------------------------
  371. // INetCfgComponentSetup                                           
  372. //                                                                       
  373. // The following functions provide the INetCfgComponentSetup interface.
  374. //                                                                       
  375. //----------------------------------------------------------------------------
  376.  
  377. // ----------------------------------------------------------------------
  378. //
  379. // Function:  CMuxNotify::Install
  380. //
  381. // Purpose:   Do operations necessary during the installation.
  382. //
  383. // Arguments:
  384. //            IN dwSetupFlags:  Setup flags
  385. //
  386. // Returns:   S_OK
  387. //
  388. // Notes:     Don't do anything irreversible (like modifying registry) yet
  389. //            since the config. actually completes only when Apply is called!
  390. //
  391.  
  392. STDMETHODIMP CMuxNotify::Install (DWORD dwSetupFlags)
  393. {
  394.  
  395.     TraceMsg( L"-->CMuxNotify INetCfgSetup::Install.\n" );
  396.  
  397.     // Start up the install process
  398.  
  399.     m_eApplyAction = eActInstall;
  400.  
  401.     TraceMsg( L"<--CMuxNotify INetCfgSetup::Install(HRESULT = %x).\n",
  402.             S_OK );
  403.  
  404.     return S_OK;
  405. }
  406.  
  407. // ----------------------------------------------------------------------
  408. //
  409. // Function:  CMuxNotify::Upgrade
  410. //
  411. // Purpose:   Do operations necessary during the upgrade.
  412. //
  413. // Arguments:
  414. //            IN dwSetupFlags: Setup flags
  415. //
  416. // Returns:   S_OK
  417. //
  418. // Notes:     Don't do anything irreversible (like modifying registry) yet
  419. //            since the config. actually completes only when Apply is called!
  420. //
  421.  
  422. STDMETHODIMP CMuxNotify::Upgrade (IN DWORD dwSetupFlags,
  423.                                   IN DWORD dwUpgradeFromBuildNo)
  424. {
  425.  
  426.     TraceMsg( L"-->CMuxNotify INetCfgSetup::Upgrade.\n" );
  427.  
  428.     TraceMsg( L"   DwSetupFlags = %x, dwUpgradeFromBuildNo = %x\n",
  429.               dwSetupFlags,
  430.               dwUpgradeFromBuildNo );
  431.  
  432.     TraceMsg( L"<--CMuxNotify INetCfgSetup::Upgrade(HRESULT = %x).\n",
  433.               S_OK );
  434.  
  435.     return S_OK;
  436. }
  437.  
  438.  
  439. // ----------------------------------------------------------------------
  440. //
  441. // Function:  CMuxNotify::ReadAnswerFile
  442. //
  443. // Purpose:   Read settings from answerfile and configure CMuxNotify
  444. //
  445. // Arguments:
  446. //            IN pszAnswerFile   : Name of AnswerFile
  447. //            IN pszAnswerSection: Name of parameters section
  448. //
  449. // Returns:
  450. //
  451. // Notes:     Don't do anything irreversible (like modifying registry) yet
  452. //            since the config. actually completes only when Apply is called!
  453. //
  454.  
  455. STDMETHODIMP CMuxNotify::ReadAnswerFile (PCWSTR pszAnswerFile,
  456.                                          PCWSTR pszAnswerSection)
  457. {
  458.     PCWSTR pszParamReadFromAnswerFile = L"ParamFromAnswerFile";
  459.  
  460.     TraceMsg( L"-->CMuxNotify INetCfgSetup::ReadAnswerFile.\n" );
  461.  
  462.     // We will pretend here that szParamReadFromAnswerFile was actually
  463.     // read from the AnswerFile using the following steps
  464.     //
  465.     //   - Open file pszAnswerFile using SetupAPI
  466.     //   - locate section pszAnswerSection
  467.     //   - locate the required key and get its value
  468.     //   - store its value in pszParamReadFromAnswerFile
  469.     //   - close HINF for pszAnswerFile
  470.  
  471.     // Now that we have read pszParamReadFromAnswerFile from the
  472.     // AnswerFile, store it in our memory structure.
  473.     // Remember we should not be writing it to the registry till
  474.     // our Apply is called!!
  475.     //
  476.  
  477.     TraceMsg( L"<--CMuxNotify INetCfgSetup::ReadAnswerFile(HRESULT = %x).\n",
  478.               S_OK );
  479.  
  480.     return S_OK;
  481. }
  482.  
  483.  
  484. // ----------------------------------------------------------------------
  485. //
  486. // Function:  CMuxNotify::Removing
  487. //
  488. // Purpose:   Do necessary cleanup when being removed
  489. //
  490. // Arguments: None
  491. //
  492. // Returns:   S_OK
  493. //
  494. // Notes:     Don't do anything irreversible (like modifying registry) yet
  495. //            since the removal is actually complete only when Apply is called!
  496. //
  497.  
  498. STDMETHODIMP CMuxNotify::Removing (VOID)
  499. {
  500.  
  501.     TraceMsg( L"-->CMuxNotify INetCfgSetup::Removing.\n" );
  502.  
  503.     TraceMsg( L"<--CMuxNotify INetCfgSetup::Removing(HRESULT = %x).\n",
  504.             S_OK );
  505.  
  506.     return S_OK;
  507. }
  508.  
  509.  
  510.  
  511. //----------------------------------------------------------------------------
  512. // INetCfgComponentNotifyBinding                                          
  513. //                                                                       
  514. // The following functions provide the INetCfgComponentNotifyBinding interface.
  515. //                                                                       
  516. //----------------------------------------------------------------------------
  517.  
  518. //----------------------------------------------------------------------------
  519. //
  520. // Function:  CMuxNotify::QueryBindingPath
  521. //
  522. // Purpose:  This is specific to the component being installed. This will 
  523. //           ask us if we want to bind to the Item being passed into
  524. //           this routine. We can disable the binding by returning
  525. //           NETCFG_S_DISABLE_QUERY 
  526. //
  527. //
  528. // Arguments:
  529. //           IN dwChangeFlag: Type of binding change
  530. //           IN pncbpItem   : Pointer to INetCfgBindingPath object
  531. //
  532. // Returns:   S_OK on success, otherwise an error code.
  533. //
  534. // Notes:
  535. //
  536. STDMETHODIMP CMuxNotify::QueryBindingPath (IN DWORD dwChangeFlag,  
  537.                                            IN INetCfgBindingPath *pncbp)
  538. {
  539.     TraceMsg( L"-->CMuxNotify INetCfgNotifyBinding::QueryBindingPath.\n" );
  540.  
  541.     DumpChangeFlag( dwChangeFlag );
  542.     DumpBindingPath( pncbp );
  543.  
  544.     TraceMsg( L"<--CMuxNotify INetCfgNotifyBinding::QueryBindingPath(HRESULT = %x).\n",
  545.             S_OK );
  546.  
  547.     return S_OK;
  548. }
  549.  
  550. // ----------------------------------------------------------------------
  551. //
  552. // Function:  CMuxNotify::NotifyBindingPath
  553. //
  554. // Purpose:  We are now being told to bind to the component passed to us. 
  555. //
  556. //
  557. // Arguments:
  558. //           IN dwChangeFlag: Type of system change
  559. //           IN pncc        : Pointer to INetCfgComponent object
  560. //
  561. // Returns:   S_OK on success, otherwise an error code
  562. //
  563. // Notes:
  564. //
  565.  
  566.  
  567.  
  568. STDMETHODIMP CMuxNotify::NotifyBindingPath (IN DWORD dwChangeFlag,  
  569.                                             IN INetCfgBindingPath *pncbp)
  570. {
  571.     INetCfgComponent     *pnccLower;
  572.     INetCfgComponent     *pnccUpper;
  573.     LPWSTR               pszwInfIdLower;
  574.     LPWSTR               pszwInfIdUpper;
  575.     DWORD                dwCharcteristics;
  576.     HRESULT              hr = S_OK;
  577.  
  578.     TraceMsg( L"-->CMuxNotify INetCfgNotifyBinding::NotifyBindingPath.\n" );
  579.  
  580.     DumpChangeFlag( dwChangeFlag );
  581.     DumpBindingPath( pncbp );
  582.  
  583.      //
  584.      // We are only interested to know 1) when a component is installed
  585.      // and we are binding to it i.e. dwChangeFlag = NCN_ADD | NCN_ENABLE
  586.      // and 2) when a component is removed to which we are bound i.e.
  587.      // dwChangeFlag = NCN_REMOVE | NCN_ENABLE. dwChangeFlag is never
  588.      // set to NCN_ADD or NCN_REMOVE only. So, checking for NCN_ENABLE
  589.      // covers the case of NCN_ADD | NCN_ENABLE and checking for NCN_REMOVE
  590.      // covers the case of NCN_REMOVE | NCN_ENABLE. We don't care about
  591.      // NCN_ADD | NCN_DISABLE (case 1) and NCN_REMOVE | NCN_DISABLE (case 2).
  592.      //
  593.  
  594.      if ( dwChangeFlag & (NCN_ENABLE | NCN_REMOVE) ) {
  595.  
  596.         //
  597.         // Get the upper and lower components.
  598.         //
  599.  
  600.         hr = HrGetUpperAndLower( pncbp,
  601.                                  &pnccUpper,
  602.                                  &pnccLower );
  603.  
  604.         if ( hr == S_OK ) {
  605.  
  606.             hr = pnccLower->GetCharacteristics( &dwCharcteristics );
  607.  
  608.             if ( hr == S_OK ) {
  609.  
  610.                 hr = pnccLower->GetId( &pszwInfIdLower );
  611.  
  612.                 if ( hr == S_OK ) {
  613.  
  614.                     hr = pnccUpper->GetId( &pszwInfIdUpper );
  615.  
  616.                     if ( hr == S_OK ) {
  617.  
  618.                         //
  619.                         // We are interested only in binding to a
  620.                         // physical ethernet adapters.
  621.                         // 
  622.  
  623.                         if ( dwCharcteristics & NCF_PHYSICAL ) {
  624.  
  625.                             if ( !_wcsicmp( pszwInfIdUpper, c_szMuxProtocol ) ) {
  626.  
  627.                                 if ( dwChangeFlag & NCN_ADD ) {
  628.  
  629.                                     hr = HrAddAdapter( pnccLower );
  630.                                     m_eApplyAction = eActAdd;
  631.  
  632.                                 } else if ( dwChangeFlag & NCN_REMOVE ) {
  633.  
  634.                                     hr = HrRemoveAdapter( pnccLower );
  635.                                     m_eApplyAction = eActRemove;
  636.                                 }
  637.                             }
  638.                         } // Physical Adapters. 
  639.                         else if (dwCharcteristics & NCF_VIRTUAL) {
  640.  
  641.                         }
  642.  
  643.                         CoTaskMemFree( pszwInfIdUpper );
  644.  
  645.                     } // Got the upper component id.
  646.  
  647.                     CoTaskMemFree( pszwInfIdLower );
  648.  
  649.                 } // Got the lower component id.
  650.  
  651.             } // Got NIC's characteristics
  652.  
  653.             ReleaseObj(pnccLower);
  654.             ReleaseObj(pnccUpper);
  655.  
  656.         } // Got the upper and lower components.
  657.  
  658.     } 
  659.  
  660.     TraceMsg( L"<--CMuxNotify INetCfgNotifyBinding::NotifyBindingPath(HRESULT = %x).\n",
  661.             S_OK );
  662.  
  663.     return S_OK;
  664. }
  665.  
  666.  
  667.  
  668.  
  669. //----------------------------------------------------------------------------
  670. // INetCfgComponentNotifyGlobal
  671. //                                                                       
  672. // The following functions provide the INetCfgComponentNotifyGlobal interface.
  673. //                                                                       
  674. //----------------------------------------------------------------------------
  675.  
  676. // ----------------------------------------------------------------------
  677. //
  678. // Function:  CMuxNotify::GetSupportedNotifications
  679. //
  680. // Purpose:   Tell the system which notifications we are interested in
  681. //
  682. // Arguments:
  683. //            OUT pdwNotificationFlag: Pointer to NotificationFlag
  684. //
  685. // Returns:   S_OK on success, otherwise an error code
  686. //
  687. // Notes:
  688. //
  689. STDMETHODIMP CMuxNotify::GetSupportedNotifications (
  690.                                              OUT DWORD* pdwNotificationFlag)
  691. {
  692.     TraceMsg( L"-->CMuxNotify INetCfgNotifyGlobal::GetSupportedNotifications.\n" );
  693.  
  694.     *pdwNotificationFlag = NCN_NET | NCN_NETTRANS | NCN_ADD | NCN_REMOVE |
  695.                            NCN_BINDING_PATH | NCN_ENABLE | NCN_DISABLE;
  696.  
  697.     TraceMsg( L"<--CMuxNotify INetCfgNotifyGlobal::GetSupportedNotifications(HRESULT = %x).\n",
  698.             S_OK );
  699.  
  700.     return S_OK;
  701. }
  702.  
  703. // ----------------------------------------------------------------------
  704. //
  705. // Function:  CMuxNotify::SysQueryBindingPath
  706. //
  707. // Purpose:   Enable or Disable a binding path.
  708. //
  709. // Arguments:
  710. //            IN dwChangeFlag: Type of binding change
  711. //            IN pncbp       : Pointer to INetCfgBindingPath object
  712. //
  713. // Returns:   S_OK on success, otherwise an error code
  714. //
  715. // Notes:
  716. //
  717.  
  718. STDMETHODIMP CMuxNotify::SysQueryBindingPath (DWORD dwChangeFlag,
  719.                                               INetCfgBindingPath* pncbp)
  720. {
  721.     INetCfgComponent     *pnccLower;
  722.     INetCfgComponent     *pnccUpper;
  723.     LPWSTR               pszwInfIdLower;
  724.     LPWSTR               pszwInfIdUpper;
  725.     DWORD                dwCharcteristics;
  726.     HRESULT              hr = S_OK;
  727.  
  728.  
  729.     TraceMsg( L"-->CMuxNotify INetCfgNotifyGlobal::SysQueryBindingPath.\n" );
  730.  
  731.     DumpChangeFlag( dwChangeFlag );
  732.     DumpBindingPath( pncbp );
  733.  
  734.     if ( dwChangeFlag & NCN_ENABLE ) {
  735.  
  736.         //
  737.         // Get the upper and lower components.
  738.         //
  739.  
  740.         hr = HrGetUpperAndLower( pncbp,
  741.                                  &pnccUpper,
  742.                                  &pnccLower );
  743.  
  744.         if ( hr == S_OK ) {
  745.             hr = pnccLower->GetCharacteristics( &dwCharcteristics );
  746.  
  747.             if ( hr == S_OK ) {
  748.  
  749.                 if ( dwCharcteristics & NCF_PHYSICAL ) {
  750.                     ULONG ulStatus;
  751.                     hr = pnccLower->GetDeviceStatus( &ulStatus );
  752.                     if ( hr != S_OK)
  753.                         hr = NETCFG_S_DISABLE_QUERY;
  754.                     else {
  755.                         LPWSTR deviceName;
  756.                         hr = pnccLower->GetDisplayName( &deviceName );
  757.                         if ( hr == S_OK ) {
  758.                             LPWSTR cisco = L"cisco";
  759.                             LPWSTR orinoco = L"orinoco";
  760.                             LPWSTR netgear = L"netgear";
  761.                             LPWSTR wlan = L"wlan";
  762.                             LPWSTR wireless = L"wireless";
  763.                             LPWSTR l_deviceName = _wcslwr(deviceName);
  764.  
  765.                             TraceMsg(L"\tVirtualWiFi Device Name: %s\n", l_deviceName);
  766.                             if ( !(wcsstr( l_deviceName, cisco ) != NULL 
  767.                                 || wcsstr( deviceName, orinoco ) != NULL
  768.                                 || wcsstr( deviceName, netgear ) != NULL
  769.                                 || wcsstr( deviceName, wireless ) != NULL
  770.                                 || wcsstr( deviceName, wlan ) != NULL ))
  771.                                 hr = NETCFG_S_DISABLE_QUERY;
  772.                             
  773.                             /*
  774.                             LPWSTR ethDevice = L"Ethernet";
  775.                             LPWSTR ethDevice1 = L"Intel";
  776.                             if ( wcsstr( deviceName, ethDevice ) != NULL )
  777.                                 hr = NETCFG_S_DISABLE_QUERY;
  778.                             if ( wcsstr( deviceName, ethDevice1 ) != NULL )
  779.                                 hr = NETCFG_S_DISABLE_QUERY;
  780.                             */
  781.                         }
  782.                         if ( hr == S_OK )
  783.                         {
  784.                             LPWSTR guidLower;
  785.                             HANDLE adapterHandle;
  786.  
  787.                             hr = pnccLower->GetBindName( &guidLower );
  788.  
  789.                             if ( hr == S_OK )
  790.                             {
  791.                                 hr = OpenInterfaceHandle( guidLower, &adapterHandle );
  792.                                 if ( hr == S_OK ) {
  793.                                     TraceMsg(L"Open Interface Handle was successful\n");
  794.                                 } else {
  795.                                     TraceMsg(L"Open Interface Handle was NOT successful\n");
  796.                                 }
  797.                                 hr = S_OK;
  798.                             }
  799.                         }
  800.                     }
  801.                 }
  802.  
  803.             }
  804.  
  805.             if ( hr == S_OK ) {
  806.  
  807.                 hr = pnccLower->GetId( &pszwInfIdLower );
  808.  
  809.                 if ( hr == S_OK ) {
  810.  
  811.                     hr = pnccUpper->GetId( &pszwInfIdUpper );
  812.  
  813.                     if ( hr == S_OK ) {
  814.  
  815.                         //
  816.                         // We are interested only in bindings to physical 
  817.                         // ethernet adapters.
  818.                         // 
  819.  
  820.                         if ( dwCharcteristics & NCF_PHYSICAL ) {
  821.                         
  822. #ifdef DISABLE_PROTOCOLS_TO_PHYSICAL
  823.  
  824.                             //
  825.                             // If it not our protocol binding to the
  826.                             // physical adapter then, disable the
  827.                             // binding.
  828.                             //
  829.  
  830.                             if (_wcsicmp( pszwInfIdUpper, c_szMuxProtocol ) ) {
  831.  
  832.                                 TraceMsg( L"   Disabling the binding between %s "
  833.                                           L"and %s.\n",
  834.                                           pszwInfIdUpper,
  835.                                           pszwInfIdLower );
  836.  
  837.                                 hr = NETCFG_S_DISABLE_QUERY;
  838.                             }
  839. #endif
  840.  
  841.                         } // Physical Adapters. 
  842.                         else {
  843.                             if (dwCharcteristics & NCF_VIRTUAL) {
  844.  
  845.                                 // If the lower component is our miniport
  846.                                 // and the upper component is our protocol
  847.                                 // then also, disable the binding.
  848.  
  849.                                 if ( !_wcsicmp(pszwInfIdLower, c_szMuxMiniport) &&
  850.                                      !_wcsicmp(pszwInfIdUpper, c_szMuxProtocol) ) {
  851.                                   
  852.                                     TraceMsg( L"   Disabling the binding between %s "
  853.                                               L"and %s.\n",
  854.                                               pszwInfIdUpper,
  855.                                               pszwInfIdLower );
  856.  
  857.                                     hr = NETCFG_S_DISABLE_QUERY;
  858.                                 }
  859.  
  860.                             } // Virtual Adapters
  861.  
  862.                         }
  863.  
  864.                         CoTaskMemFree( pszwInfIdUpper );
  865.  
  866.                     } // Got the upper component id.
  867.  
  868.                     CoTaskMemFree( pszwInfIdLower );
  869.  
  870.                 } // Got the lower component id.
  871.  
  872.             } // Got NIC's characteristics
  873.  
  874.             ReleaseObj(pnccLower);
  875.             ReleaseObj(pnccUpper);
  876.  
  877.         }
  878.  
  879.     }
  880.  
  881.     TraceMsg( L"<--CMuxNotify INetCfgNotifyGlobal::SysQueryBindingPath(HRESULT = %x).\n",
  882.             hr );
  883.  
  884.     return hr;
  885. }
  886.  
  887. // ----------------------------------------------------------------------
  888. //
  889. // Function:  CMuxNotify::SysNotifyBindingPath
  890. //
  891. // Purpose:   System tells us by calling this function which
  892. //            binding path has just been formed.
  893. //
  894. // Arguments:
  895. //            IN dwChangeFlag: Type of binding change
  896. //            IN pncbpItem   : Pointer to INetCfgBindingPath object
  897. //
  898. // Returns:   S_OK on success, otherwise an error code
  899. //
  900. // Notes:
  901. //
  902. STDMETHODIMP CMuxNotify::SysNotifyBindingPath (DWORD dwChangeFlag,
  903.                                                INetCfgBindingPath* pncbp)
  904. {
  905.     TraceMsg( L"-->CMuxNotify INetCfgNotifyGlobal::SysNotifyBindingPath.\n" );
  906.  
  907.     DumpChangeFlag( dwChangeFlag );
  908.     DumpBindingPath( pncbp );
  909.  
  910.     TraceMsg( L"<--CMuxNotify INetCfgNotifyGlobal::SysNotifyBindingPath(HRESULT = %x).\n",
  911.             S_OK );
  912.  
  913.     return S_OK;
  914. }
  915.  
  916. // ----------------------------------------------------------------------
  917. //
  918. // Function:  CMuxNotify::SysNotifyComponent
  919. //
  920. // Purpose:   System tells us by calling this function which
  921. //            component has undergone a change (installed/removed)
  922. //
  923. // Arguments:
  924. //            IN dwChangeFlag: Type of system change
  925. //            IN pncc        : Pointer to INetCfgComponent object
  926. //
  927. // Returns:   S_OK on success, otherwise an error code
  928. //
  929. // Notes:
  930. //
  931. STDMETHODIMP CMuxNotify::SysNotifyComponent (DWORD dwChangeFlag,
  932.                                                 INetCfgComponent* pncc)
  933. {
  934.     TraceMsg( L"-->CMuxNotify INetCfgNotifyGlobal::SysNotifyComponent.\n" );
  935.  
  936.     DumpChangeFlag( dwChangeFlag );
  937.     DumpComponent( pncc );
  938.  
  939.     TraceMsg( L"<--CMuxNotify INetCfgNotifyGlobal::SysNotifyComponent(HRESULT = %x).\n",
  940.             S_OK );
  941.  
  942.     return S_OK;
  943. }
  944.  
  945.  
  946. //----------------------------------------------------------------------------
  947. // INetCfgComponentPropertyUi                                          
  948. //                                                                       
  949. // The following functions provide the INetCfgComponentPropertyUi interface.
  950. //                                                                       
  951. //----------------------------------------------------------------------------
  952.  
  953. // ----------------------------------------------------------------------
  954. //
  955. // Function:  CMuxNotify::MergePropPages
  956. //
  957. // Purpose:   Supply our property page to system.
  958. //
  959. // Arguments:
  960. //            OUT pdwDefPages  : Pointer to num default pages
  961. //            OUT pahpspPrivate: Pointer to array of pages
  962. //            OUT pcPages      : Pointer to num pages
  963. //            IN  hwndParent   : Handle of parent window
  964. //            IN  szStartPage  : Pointer to
  965. //
  966. // Returns:   S_OK on success, otherwise an error code
  967. //
  968. // Notes:
  969. //
  970. STDMETHODIMP CMuxNotify::MergePropPages (IN OUT DWORD* pdwDefPages,
  971.                                          OUT LPBYTE* pahpspPrivate,
  972.                                          OUT UINT* pcPages,
  973.                                          IN HWND hwndParent,
  974.                                          OUT PCWSTR* szStartPage)
  975. {
  976.     HRESULT                 hr = S_OK;
  977.     HPROPSHEETPAGE          *ahpsp;;
  978.     INetLanConnectionUiInfo *pLanConnUiInfo;
  979.  
  980.     TraceMsg(L"-->CMuxNotify INetCfgPropertyUi::MergePropPages\n");
  981.  
  982.     //
  983.     // We don't want any default pages to be shown
  984.     //
  985.  
  986.     *pdwDefPages = 0;
  987.     *pcPages = 0;
  988.     *pahpspPrivate = NULL;
  989.  
  990.     if ( !m_pUnkContext ) {
  991.         return E_UNEXPECTED;
  992.     }
  993.  
  994.     hr = m_pUnkContext->QueryInterface(
  995.           IID_INetLanConnectionUiInfo,
  996.           reinterpret_cast<PVOID *>(&pLanConnUiInfo));
  997.  
  998.     if ( hr == S_OK ) {
  999.  
  1000.         ReleaseObj( pLanConnUiInfo );
  1001.  
  1002.         ahpsp = (HPROPSHEETPAGE*)CoTaskMemAlloc( sizeof(HPROPSHEETPAGE) );
  1003.  
  1004.         if (ahpsp) {
  1005.  
  1006.             PROPSHEETPAGE   psp = {0};
  1007.  
  1008.             psp.dwSize            = sizeof(PROPSHEETPAGE);
  1009.             psp.dwFlags           = PSP_DEFAULT;
  1010.             psp.hInstance         = _Module.GetModuleInstance();
  1011.             psp.pszTemplate       = MAKEINTRESOURCE(IDD_NOTIFY_GENERAL);
  1012.             psp.pfnDlgProc        = (DLGPROC)NotifyDialogProc;
  1013.             psp.pfnCallback       = NULL; (LPFNPSPCALLBACK)NotifyPropSheetPageProc;
  1014.             psp.lParam            = (LPARAM) this;
  1015.             psp.pszHeaderTitle    = NULL;
  1016.             psp.pszHeaderSubTitle = NULL;
  1017.  
  1018.             ahpsp[0] = ::CreatePropertySheetPage(&psp);
  1019.             *pcPages = 1;
  1020.             *pahpspPrivate = (LPBYTE)ahpsp;
  1021.         }
  1022.         else {
  1023.             hr = E_OUTOFMEMORY;
  1024.         }
  1025.     }
  1026.     TraceMsg(L"<--CMuxNotify INetCfgPropertyUi::MergePropPages(HRESULT = %x).\n",
  1027.            hr );
  1028.  
  1029.     return hr;
  1030. }
  1031.  
  1032.  
  1033. // ----------------------------------------------------------------------
  1034. //
  1035. // Function:  CMuxNotify::ValidateProperties
  1036. //
  1037. // Purpose:   Validate changes to property page.
  1038. //
  1039. // Arguments:
  1040. //            IN hwndSheet: Window handle of property sheet
  1041. //
  1042. // Returns:   S_OK on success, otherwise an error code
  1043. //
  1044. // Notes:
  1045. //
  1046.  
  1047. STDMETHODIMP CMuxNotify::ValidateProperties (HWND hwndSheet)
  1048. {
  1049.  
  1050.     TraceMsg( L"-->CMuxNotify INetCfgPropertyUi::ValidateProperties\n" );
  1051.  
  1052.     TraceMsg(L"<--CMuxNotify INetCfgPropertyUi::ValidateProperties(HRESULT = %x).\n",
  1053.            S_OK );
  1054.     return S_OK;
  1055. }
  1056.  
  1057. // ----------------------------------------------------------------------
  1058. //
  1059. // Function:  CMuxNotify::CancelProperties
  1060. //
  1061. // Purpose:   Cancel changes to property page
  1062. //
  1063. // Arguments: None
  1064. //
  1065. // Returns:   S_OK on success, otherwise an error code
  1066. //
  1067. // Notes:
  1068. //
  1069. STDMETHODIMP CMuxNotify::CancelProperties (VOID)
  1070. {
  1071.     TraceMsg(L"-->CMuxNotify INetCfgPropertyUi::CancelProperties\n");
  1072.  
  1073.     TraceMsg(L"<--CMuxNotify INetCfgPropertyUi::CancelProperties(HRESULT = %x).\n",
  1074.            S_OK );
  1075.  
  1076.     return S_OK;
  1077. }
  1078.  
  1079. // ----------------------------------------------------------------------
  1080. //
  1081. // Function:  CMuxNotify::ApplyProperties
  1082. //
  1083. // Purpose:   Apply value of controls on property page
  1084. //            to internal memory structure
  1085. //
  1086. // Arguments: None
  1087. //
  1088. // Returns:   S_OK on success, otherwise an error code
  1089. //
  1090. // Notes:     
  1091. //
  1092. STDMETHODIMP CMuxNotify::ApplyProperties (VOID)
  1093. {
  1094.     INetLanConnectionUiInfo *pLanConnUiInfo;
  1095.     CMuxPhysicalAdapter     *pAdapter;
  1096.     GUID                    guidAdapter;
  1097.     INetCfgComponent        *pncc;
  1098.     HRESULT                 hr = S_OK;
  1099.  
  1100.     TraceMsg(L"-->CMuxNotify INetCfgPropertyUi::ApplyProperties\n");
  1101.  
  1102.     if ( m_pUnkContext ) {
  1103.  
  1104.         hr = m_pUnkContext->QueryInterface(
  1105.                                   IID_INetLanConnectionUiInfo,
  1106.                                   reinterpret_cast<PVOID *>(&pLanConnUiInfo));
  1107.  
  1108.         if ( hr == S_OK ) {
  1109.  
  1110.             hr = pLanConnUiInfo->GetDeviceGuid( &guidAdapter );
  1111.  
  1112.             if ( hr == S_OK ) {
  1113.  
  1114.                 hr = m_AdaptersList.FindByKey( guidAdapter,
  1115.                                                &pAdapter );
  1116.                 if ( hr == S_OK ) {
  1117.  
  1118.                     switch( m_eApplyAction ) {
  1119.  
  1120.                         case eActPropertyUIAdd:
  1121.  
  1122.                               hr = HrAddMiniport( pAdapter,
  1123.                                                   &guidAdapter );
  1124.                         break;
  1125.  
  1126.                         case eActPropertyUIRemove:
  1127.  
  1128.                               hr = HrRemoveMiniport( pAdapter,
  1129.                                                      &guidAdapter );
  1130.                         break;
  1131.                     }
  1132.                 }
  1133.             }
  1134.  
  1135.             ReleaseObj( pLanConnUiInfo );
  1136.         }
  1137.     }
  1138.  
  1139.     TraceMsg(L"<--CMuxNotify INetCfgPropertyUi::ApplyProperties(HRESULT = %x).\n",
  1140.            hr );
  1141.     return hr;
  1142. }
  1143.  
  1144. // ----------------------------------------------------------------------
  1145. //
  1146. // Function:  CMuxNotify::QueryPropertyUi
  1147. //
  1148. // Purpose:   System is asking if we support property pages.
  1149. //
  1150. // Arguments:
  1151. //            IN pUnk: Pointer to IUnknown.
  1152. //
  1153. // Returns:   S_OK on success, otherwise an error code
  1154. //
  1155. // Notes:     We display property pages only in the context of
  1156. //            a LAN connection.
  1157. //
  1158.  
  1159. STDMETHODIMP CMuxNotify::QueryPropertyUi (IUnknown * pUnk)
  1160. {
  1161.     INetLanConnectionUiInfo *pLanConnUiInfo;
  1162.     HRESULT                 hr=S_FALSE;
  1163.  
  1164.     TraceMsg(L"-->CMuxNotify INetCfgPropertyUi::QueryPropertyUi\n");
  1165.  
  1166. #ifndef PASSTHRU_NOTIFY
  1167.  
  1168.     if ( pUnk ) {
  1169.  
  1170.         hr = pUnk->QueryInterface(
  1171.                               IID_INetLanConnectionUiInfo,
  1172.                               reinterpret_cast<PVOID *>(&pLanConnUiInfo));
  1173.  
  1174.         ReleaseObj( pLanConnUiInfo );
  1175.     } 
  1176. #endif
  1177.  
  1178.     TraceMsg(L"<--CMuxNotify INetCfgPropertyUi::QueryPropertyUi(HRESULT = %x).\n",
  1179.            hr );
  1180.  
  1181.     return hr;
  1182. }
  1183.  
  1184. // ----------------------------------------------------------------------
  1185. //
  1186. // Function:  CMuxNotify::SetContext
  1187. //
  1188. // Purpose:   Save the LAN connection context.
  1189. //
  1190. // Arguments: 
  1191. //            IN pUnk: Pointer to IUnknown.
  1192. //
  1193. // Returns:   S_OK on success, otherwise an error code
  1194. //
  1195. // Notes:     It is also called to release the current LAN connection context.
  1196. //
  1197.  
  1198. STDMETHODIMP CMuxNotify::SetContext (IUnknown * pUnk)
  1199. {
  1200.     TraceMsg(L"-->CMuxNotify INetCfgPropertyUi::SetContext\n");
  1201.  
  1202.     //
  1203.     // Release previous context, if any
  1204.     //
  1205.  
  1206.     ReleaseObj( m_pUnkContext );
  1207.  
  1208.     m_pUnkContext = NULL;
  1209.  
  1210.     if ( pUnk ) {
  1211.  
  1212.         m_pUnkContext = pUnk;
  1213.         m_pUnkContext->AddRef();
  1214.     }
  1215.  
  1216.     TraceMsg(L"<--CMuxNotify INetCfgPropertyUi::SetContext(HRESULT = %x).\n",
  1217.            S_OK );
  1218.  
  1219.     return S_OK;
  1220. }
  1221.  
  1222. //----------------------------------------------------------------------------
  1223. //
  1224. //  Function:   CMuxNotify::HrLoadAdapterConfiguration
  1225. //
  1226. //  Purpose:    This loads the Miniport and adapters that have already been 
  1227. //              installed into our own data structures
  1228. //
  1229. //  Arguments:  None.
  1230. //
  1231. //  Returns:    S_OK, or an error.
  1232. //
  1233. //
  1234. //  Notes:
  1235. //
  1236.  
  1237.  
  1238. HRESULT CMuxNotify::HrLoadAdapterConfiguration (VOID)
  1239. {
  1240.     HKEY                 hkeyAdapterList;
  1241.     WCHAR                szAdapterGuid[MAX_PATH+1];
  1242.     DWORD                dwDisp;
  1243.     CMuxPhysicalAdapter  *pAdapter;
  1244.     GUID                 guidAdapter;
  1245.     DWORD                dwIndex;
  1246.     LONG                 lResult;
  1247.  
  1248.     TraceMsg( L"-->CMuxNotify::HrLoadAdapterConfiguration.\n" );
  1249.  
  1250.     lResult = RegCreateKeyExW( HKEY_LOCAL_MACHINE,
  1251.                                c_szAdapterList,
  1252.                                0,
  1253.                                NULL,
  1254.                                REG_OPTION_NON_VOLATILE,
  1255.                                KEY_ALL_ACCESS,
  1256.                                NULL,
  1257.                                &hkeyAdapterList,
  1258.                                &dwDisp);
  1259.  
  1260.  
  1261.     if ( lResult == ERROR_SUCCESS ) {
  1262.  
  1263.         //
  1264.         // If dwDisp indicates that a new key is created then, we know there
  1265.         // is no adapter currently listed underneath and we simply
  1266.         // return, otherwise, we enumerate the subkeys, each one representing an 
  1267.         // adapter.
  1268.         //
  1269.  
  1270.         if ( dwDisp != REG_CREATED_NEW_KEY ) {
  1271.  
  1272.             lResult = RegEnumKeyW( hkeyAdapterList,
  1273.                                    0,
  1274.                                    szAdapterGuid,
  1275.                                    MAX_PATH+1 );
  1276.  
  1277.             for (dwIndex=1; lResult == ERROR_SUCCESS; ++dwIndex) {
  1278.  
  1279.                 TraceMsg( L"   Loading configuration for adapter %s...\n",
  1280.                          szAdapterGuid );
  1281.  
  1282.                 //
  1283.                 // Subkeys are actually a guid/bindname of the adapters.
  1284.                 //
  1285.  
  1286.                 CLSIDFromString( szAdapterGuid,
  1287.                                  &guidAdapter );
  1288.  
  1289.                 //
  1290.                 // Create an instance representing the adapter.
  1291.                 //
  1292.  
  1293.                 pAdapter = new CMuxPhysicalAdapter( m_pnc,
  1294.                                                     &guidAdapter );
  1295.  
  1296.                 if ( pAdapter ) {
  1297.  
  1298.                   //
  1299.                   // Load any adapter specific configuration.
  1300.                   //
  1301.  
  1302.                   pAdapter->LoadConfiguration();
  1303.  
  1304.                   //
  1305.                   // Save the adapter instance in a list.
  1306.                   //
  1307.  
  1308.                   m_AdaptersList.Insert( pAdapter,
  1309.                                          guidAdapter );
  1310.  
  1311.                   //
  1312.                   // Get next subkey.
  1313.                   //
  1314.  
  1315.                   lResult = RegEnumKeyW( hkeyAdapterList,
  1316.                                          dwIndex,
  1317.                                          szAdapterGuid,
  1318.                                          MAX_PATH+1 );
  1319.                 }
  1320.                 else {
  1321.  
  1322.                  lResult = ERROR_NOT_ENOUGH_MEMORY;
  1323.                 }
  1324.             }
  1325.  
  1326.             //
  1327.             // RegEnumKeyW may have returned error when there are no more
  1328.             // subkeys to read.
  1329.             //
  1330.  
  1331.             lResult = ERROR_SUCCESS;
  1332.         }
  1333.  
  1334.         RegCloseKey( hkeyAdapterList );
  1335.     }
  1336.  
  1337.     TraceMsg( L"<--CMuxNotify::HrLoadAdapterConfiguration(HRESULT = %x).\n",
  1338.               HRESULT_FROM_WIN32(lResult) );
  1339.  
  1340.     return HRESULT_FROM_WIN32(lResult);
  1341. }
  1342.  
  1343. //----------------------------------------------------------------------------
  1344. //
  1345. //  Function:   CMuxNotify::HrGetUpperAndLower
  1346. //
  1347. //  Purpose:    Get the upper and lower component of the first interface
  1348. //              of a binding path.
  1349. //
  1350. //  Arguments:  
  1351. //              IN  pncbp     : Binding path.
  1352. //              OUT ppnccUpper: Upper component.
  1353. //              OUT ppnccLower: Lower component.
  1354. //
  1355. //  Returns:    S_OK, or an error.
  1356. //
  1357. //
  1358. //  Notes:
  1359. //
  1360.  
  1361. HRESULT CMuxNotify::HrGetUpperAndLower (INetCfgBindingPath* pncbp,
  1362.                                         INetCfgComponent **ppnccUpper,
  1363.                                         INetCfgComponent **ppnccLower)
  1364. {
  1365.     IEnumNetCfgBindingInterface*    pencbi;
  1366.     INetCfgBindingInterface*        pncbi;
  1367.     ULONG                           ulCount;
  1368.     HRESULT                         hr;
  1369.  
  1370.     TraceMsg( L"-->CMuxNotify::HrGetUpperAndLowerComponent.\n" );
  1371.  
  1372.     *ppnccUpper = NULL;
  1373.     *ppnccLower = NULL;
  1374.  
  1375.     hr = pncbp->EnumBindingInterfaces(&pencbi);
  1376.  
  1377.     if (S_OK == hr) {
  1378.      
  1379.         //
  1380.         // get the first binding interface
  1381.         //
  1382.  
  1383.         hr = pencbi->Next(1, &pncbi, &ulCount);
  1384.  
  1385.         if ( hr == S_OK ) {
  1386.  
  1387.             hr = pncbi->GetUpperComponent( ppnccUpper );
  1388.  
  1389.             if ( hr == S_OK ) {
  1390.  
  1391.                 hr = pncbi->GetLowerComponent ( ppnccLower );
  1392.             }
  1393.             else {
  1394.                 ReleaseObj( *ppnccUpper );
  1395.             }
  1396.  
  1397.             ReleaseObj( pncbi );
  1398.         }
  1399.  
  1400.         ReleaseObj( pencbi );
  1401.     }
  1402.  
  1403.     TraceMsg( L"<--CMuxNotify::HrGetUpperAndLowerComponent(HRESULT = %x).\n",
  1404.             hr );
  1405.  
  1406.     return hr;
  1407. }
  1408.  
  1409. //----------------------------------------------------------------------------
  1410. //
  1411. //  Function:   CMuxNotify::HrAddAdapter
  1412. //
  1413. //  Purpose:    Create an instance representing the physical adapter and install
  1414. //              a virtual miniport.
  1415. //
  1416. //  Arguments:  
  1417. //              IN pnccAdapter: Pointer to the physical adapter.
  1418. //
  1419. //  Returns:    S_OK, or an error.
  1420. //
  1421. //
  1422. //  Notes:
  1423. //
  1424.  
  1425. HRESULT CMuxNotify::HrAddAdapter (INetCfgComponent *pnccAdapter)
  1426. {
  1427.     GUID                     guidAdapter;
  1428.     CMuxPhysicalAdapter      *pAdapter;
  1429.     HRESULT                  hr;
  1430.  
  1431.     TraceMsg( L"-->CMuxNotify::HrAddAdapter.\n" );
  1432.  
  1433.     hr = pnccAdapter->GetInstanceGuid( &guidAdapter );
  1434.  
  1435.     if ( hr == S_OK ) {
  1436.  
  1437.         pAdapter = new CMuxPhysicalAdapter( m_pnc,
  1438.                                             &guidAdapter );
  1439.  
  1440.         if ( pAdapter ) {
  1441.             LPWSTR guidLower;
  1442.             HANDLE adapterHandle;
  1443.  
  1444.             hr = pnccAdapter->GetBindName( &guidLower );
  1445.  
  1446.             if ( hr == S_OK )
  1447.             {
  1448.                 hr = OpenInterfaceHandle( guidLower, &adapterHandle );
  1449.                 if ( hr == S_OK ) {
  1450.                     TraceMsg(L"Open Interface Handle was successful\n");
  1451.                 } else {
  1452.                     TraceMsg(L"Open Interface Handle was NOT successful\n");
  1453.                 }
  1454.                 hr = S_OK;
  1455.             }
  1456.  
  1457.             
  1458.             hr = HrAddMiniport( pAdapter,
  1459.                                 &guidAdapter );
  1460.             
  1461.             if ( hr == S_OK ) {
  1462.  
  1463.                m_AdaptersToAdd.Insert( pAdapter,
  1464.                                        guidAdapter );
  1465.             }
  1466.             else {
  1467.  
  1468.                delete pAdapter;
  1469.             }
  1470.         }
  1471.         else {
  1472.             hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  1473.         }
  1474.     } 
  1475.  
  1476.     TraceMsg( L"<--CMuxNotify::HrAddAdapter(HRESULT = %x).\n",
  1477.             hr );
  1478.  
  1479.     return hr;
  1480. }
  1481.  
  1482. //----------------------------------------------------------------------------
  1483. //
  1484. //  Function:   CMuxNotify::HrRemoveAdapter
  1485. //
  1486. //  Purpose:    Deletes the instance representing the physical adapter
  1487. //              and uninstalls all the virtual miniports.
  1488. //
  1489. //  Arguments:  
  1490. //              IN pnccAdapter: Pointer to the physical adapter.
  1491. //
  1492. //  Returns:    S_OK, or an error.
  1493. //
  1494. //
  1495. //  Notes:      This function is called when the adapter or the protocol
  1496. //              is being uninstalled.
  1497. //
  1498.  
  1499. HRESULT CMuxNotify::HrRemoveAdapter (INetCfgComponent *pnccAdapter)
  1500. {
  1501.     GUID                  guidAdapter;
  1502.     CMuxPhysicalAdapter   *pAdapter;
  1503.     HRESULT               hr;
  1504.  
  1505.     TraceMsg( L"-->CMuxNotify::HrRemoveAdapter.\n" );
  1506.  
  1507.     hr = pnccAdapter->GetInstanceGuid( &guidAdapter );
  1508.  
  1509.     if ( hr == S_OK ) {
  1510.  
  1511.         hr = m_AdaptersList.RemoveByKey( guidAdapter,
  1512.                                       &pAdapter );
  1513.  
  1514.          if ( hr == S_OK ) {
  1515.  
  1516.             m_AdaptersToRemove.Insert( pAdapter,  
  1517.                                        guidAdapter );
  1518.             hr = pAdapter->Remove();
  1519.  
  1520. #ifdef DISABLE_PROTOCOLS_TO_PHYSICAL
  1521.  
  1522.             //
  1523.             // Restore the bindings of other protocols to the physical
  1524.             // adapter.
  1525.             //
  1526.  
  1527.             EnableBindings( pnccAdapter,
  1528.                             TRUE );
  1529. #endif
  1530.          }
  1531.     }
  1532.  
  1533.     TraceMsg( L"<--CMuxNotify::HrRemoveAdapter(HRESULT = %x).\n",
  1534.             hr );
  1535.  
  1536.     return hr;
  1537. }
  1538.  
  1539. //----------------------------------------------------------------------------
  1540. //
  1541. //  Function:   CMuxNotify::HrAddMiniport
  1542. //
  1543. //  Purpose:    Installs a virtual miniport.
  1544. //
  1545. //  Arguments:  
  1546. //              IN pAdapter    : Pointer to the physical adapter class instance.
  1547. //              IN pguidAdapter: Pointer to the GUID of the adapter.
  1548. //
  1549. //  Returns:    S_OK, or an error.
  1550. //
  1551. //
  1552. //  Notes:      
  1553. //
  1554.  
  1555. HRESULT CMuxNotify::HrAddMiniport (CMuxPhysicalAdapter *pAdapter,
  1556.                                    GUID *pguidAdapter)
  1557. {
  1558.     CMuxVirtualMiniport   *pMiniport;
  1559.     INetCfgComponent      *pnccAdapter;
  1560.     HRESULT               hr;
  1561.  
  1562.     TraceMsg( L"-->CMuxNotify::HrAddMiniport.\n" );
  1563.  
  1564.     pMiniport = new CMuxVirtualMiniport( m_pnc,
  1565.                                          NULL,
  1566.                                          pguidAdapter );
  1567.     if ( pMiniport ) {
  1568.  
  1569.         hr = pMiniport->Install();
  1570.  
  1571.         if ( hr == S_OK ) {
  1572.  
  1573.             hr = pAdapter->AddMiniport( pMiniport );
  1574.  
  1575.             if ( hr != S_OK ) {
  1576.  
  1577.                 pMiniport->DeInstall();
  1578.  
  1579.                 delete pMiniport;
  1580.             }
  1581.         }
  1582.     }
  1583.     else {
  1584.  
  1585.         hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  1586.     }
  1587.  
  1588. #ifdef DISABLE_PROTOCOLS_TO_PHYSICAL
  1589.  
  1590.     if ( hr == S_OK ) {
  1591.  
  1592.         //
  1593.         // If this is the first virtual miniport then, disable the bindings
  1594.         // of other protocols to the physical adapter.
  1595.         //
  1596.  
  1597.         if ( pAdapter->MiniportCount() == 0 ) {
  1598.  
  1599.             hr = HrFindInstance( m_pnc,
  1600.                                  *pguidAdapter,
  1601.                                  &pnccAdapter );
  1602.  
  1603.             if ( hr == S_OK ) {
  1604.                 EnableBindings( pnccAdapter,
  1605.                                 FALSE );
  1606.  
  1607.                 ReleaseObj( pnccAdapter );
  1608.             }
  1609.         }
  1610.     }
  1611. #endif
  1612.  
  1613.     TraceMsg( L"<--CMuxNotify::HrAddMiniport(HRESULT = %x).\n",
  1614.             hr );
  1615.     return hr;
  1616. }
  1617.  
  1618. //----------------------------------------------------------------------------
  1619. //
  1620. //  Function:   CMuxNotify::HrRemoveMiniport
  1621. //
  1622. //  Purpose:    Uninstalls a virtual miniport.
  1623. //
  1624. //  Arguments:  
  1625. //              IN pAdapter    : Pointer to the physical adapter class instance.
  1626. //              IN pguidAdapter: Pointer to the GUID of the adapter.
  1627. //
  1628. //  Returns:    S_OK, or an error.
  1629. //
  1630. //
  1631. //  Notes:      
  1632. //
  1633.  
  1634. HRESULT CMuxNotify::HrRemoveMiniport (CMuxPhysicalAdapter *pAdapter,
  1635.                                       GUID *pguidAdapter)
  1636. {
  1637.     INetCfgComponent      *pnccAdapter;
  1638.     HRESULT                hr;
  1639.  
  1640.     TraceMsg( L"-->CMuxNotify::HrRemoveMiniport.\n" );
  1641.  
  1642.     hr = pAdapter->RemoveMiniport( NULL );
  1643.  
  1644. #ifdef DISABLE_PROTOCOLS_TO_PHYSICAL
  1645.  
  1646.     if ( hr == S_OK ) {
  1647.  
  1648.         //
  1649.         // If this was the last miniport that was removed then, restore the
  1650.         // bindings of other protocols to the physical adapter.
  1651.         //
  1652.  
  1653.         if ( pAdapter->AllMiniportsRemoved() ) {
  1654.  
  1655.             hr = HrFindInstance( m_pnc,
  1656.                                  *pguidAdapter,
  1657.                                  &pnccAdapter );
  1658.  
  1659.             if ( hr == S_OK ) {
  1660.                 EnableBindings( pnccAdapter,
  1661.                                 TRUE );
  1662.  
  1663.                 ReleaseObj( pnccAdapter );
  1664.             }
  1665.         }
  1666.     }
  1667. #endif
  1668.  
  1669.     TraceMsg( L"<--CMuxNotify::HrRemoveMiniport(HRESULT = %x).\n",
  1670.             hr );
  1671.  
  1672.     return hr;
  1673. }
  1674.  
  1675. // ----------------------------------------------------------------------
  1676. //
  1677. // Function:  CMuxNotify::OnInitDialog
  1678. //
  1679. // Purpose:   Initialize controls
  1680. //
  1681. // Arguments:
  1682. //            IN hWnd: Window handle to the property page.
  1683. //
  1684. // Returns: TRUE.
  1685. //
  1686. // Notes:
  1687. //
  1688.  
  1689. LRESULT CMuxNotify::OnInitDialog (IN HWND hWndPage)
  1690. {
  1691.     m_eApplyAction = eActUnknown;
  1692.  
  1693.     ::SendMessage(GetDlgItem(hWndPage, IDC_ADD), BM_SETCHECK, BST_CHECKED, 0);
  1694.     ::SendMessage(GetDlgItem(hWndPage, IDC_REMOVE), BM_SETCHECK, BST_UNCHECKED, 0);
  1695.  
  1696.     return TRUE;
  1697. }
  1698.  
  1699. // ----------------------------------------------------------------------
  1700. //
  1701. // Function:  CMuxNotify::OnOk
  1702. //
  1703. // Purpose:   Do actions when OK is pressed
  1704. //
  1705. // Arguments:
  1706. //            IN hWnd: Window handle to the property page.
  1707. //
  1708. // Returns:   PSNRET_NOERROR
  1709. //
  1710. // Notes:
  1711. //
  1712.  
  1713. LRESULT CMuxNotify::OnOk (IN HWND hWndPage)
  1714. {
  1715.     TraceMsg(L"-->CMuxNotify::OnOk\n");
  1716.  
  1717.     if ( ::SendMessage(GetDlgItem(hWndPage, IDC_ADD),
  1718.                        BM_GETCHECK, 0, 0) == BST_CHECKED ) {
  1719.      
  1720.         m_eApplyAction = eActPropertyUIAdd;
  1721.     }
  1722.     else {
  1723.         m_eApplyAction = eActPropertyUIRemove;
  1724.     }
  1725.  
  1726.     //
  1727.     // Set the property sheet changed flag if any of our controls
  1728.     // get changed.  This is important so that we get called to
  1729.     // apply our property changes.
  1730.     //
  1731.  
  1732.     PropSheet_Changed( GetParent(hWndPage), hWndPage);
  1733.  
  1734.     TraceMsg(L"<--CMuxNotify::OnOk(Action = %s).\n",
  1735.            (m_eApplyAction == eActPropertyUIAdd) ? L"Add" : L"Remove" );
  1736.  
  1737.     return PSNRET_NOERROR;
  1738. }
  1739.  
  1740. // ----------------------------------------------------------------------
  1741. //
  1742. // Function:  CMuxNotify::OnCancel
  1743. //
  1744. // Purpose:   Do actions when CANCEL is pressed
  1745. //
  1746. // Arguments:
  1747. //            IN hWnd: Window handle to the property page.
  1748. //
  1749. // Returns:   FALSE
  1750. //
  1751. // Notes:
  1752. //
  1753. LRESULT CMuxNotify::OnCancel (IN HWND hWndPage)
  1754. {
  1755.     TraceMsg(L"-->CMuxNotify::OnCancel\n");
  1756.  
  1757.     m_eApplyAction = eActUnknown;
  1758.  
  1759.     TraceMsg(L"<--CMuxNotify::OnCancel\n");
  1760.  
  1761.     return FALSE;
  1762. }
  1763.  
  1764. // ----------------------------------------------------------------------
  1765. //
  1766. // Function:  CMuxNotifyDialogProc
  1767. //
  1768. // Purpose:   Dialog proc
  1769. //
  1770. // Arguments:
  1771. //            IN hWnd  : See win32 documentation.
  1772. //            IN uMsg  : See win32 documentation.
  1773. //            IN wParam: See win32 documentation.
  1774. //            IN lParam: See win32 documentation.
  1775. //
  1776. // Returns:   See win32 documentation.
  1777. //
  1778. // Notes:
  1779. //
  1780. LRESULT CALLBACK NotifyDialogProc (HWND hWnd,
  1781.                                    UINT uMsg,
  1782.                                    WPARAM wParam,
  1783.                                    LPARAM lParam)
  1784. {
  1785.     CMuxNotify     *psf;
  1786.     LRESULT        lRes=FALSE;
  1787.  
  1788.     if ( uMsg != WM_INITDIALOG ) {
  1789.  
  1790.         psf = (CMuxNotify *)::GetWindowLongPtr( hWnd,
  1791.                                                 DWLP_USER );
  1792.  
  1793.         // Until we get WM_INITDIALOG, just return FALSE
  1794.  
  1795.         if ( !psf ) {
  1796.  
  1797.             return lRes;
  1798.         }
  1799.     }
  1800.  
  1801.     switch( uMsg ) {
  1802.  
  1803.         case WM_INITDIALOG:
  1804.         {
  1805.             PROPSHEETPAGE* ppsp;
  1806.             ppsp = (PROPSHEETPAGE *)lParam;
  1807.  
  1808.             psf = (CMuxNotify *)ppsp->lParam;
  1809.  
  1810.             SetWindowLongPtr( hWnd,
  1811.                           DWLP_USER,
  1812.                           (LONG_PTR)psf);
  1813.  
  1814.             lRes = psf->OnInitDialog( hWnd );
  1815.         }
  1816.         break;
  1817.  
  1818.         case WM_COMMAND:
  1819.  
  1820.         break;
  1821.  
  1822.         case WM_NOTIFY:
  1823.         {
  1824.             LPNMHDR pnmh = (LPNMHDR)lParam;
  1825.  
  1826.             switch (pnmh->code) {
  1827.         
  1828.             case PSN_KILLACTIVE:
  1829.  
  1830.                 //
  1831.                 // ok to loose focus.
  1832.                 //
  1833.  
  1834.                 SetWindowLongPtr( hWnd, DWLP_MSGRESULT, FALSE);
  1835.  
  1836.                 lRes = TRUE;
  1837.                 break;
  1838.  
  1839.             case PSN_APPLY:
  1840.  
  1841.                 psf = (CMuxNotify *)::GetWindowLongPtr( hWnd, DWLP_USER);
  1842.                 lRes = psf->OnOk( hWnd );
  1843.  
  1844.                 SetWindowLongPtr( hWnd, DWLP_MSGRESULT, lRes);
  1845.                 lRes = TRUE;
  1846.                 break;
  1847.  
  1848.             case PSN_RESET:
  1849.  
  1850.                 psf = (CMuxNotify *)::GetWindowLongPtr( hWnd, DWLP_USER);
  1851.                 psf->OnCancel( hWnd );
  1852.         }
  1853.      }
  1854.   }
  1855.  
  1856.   return lRes;
  1857. }
  1858.  
  1859. // ----------------------------------------------------------------------
  1860. //
  1861. // Function:  CMuxNotifyPropSheetPageProc
  1862. //
  1863. // Purpose:   Prop sheet proc
  1864. //
  1865. // Arguments:
  1866. //            IN hWnd: See win32 documentation
  1867. //            IN uMsg: See win32 documentation
  1868. //            IN ppsp: See win32 documentation
  1869. //
  1870. // Returns:   See win32 documentation
  1871. //
  1872. // Notes:
  1873. //
  1874.  
  1875. UINT CALLBACK NotifyPropSheetPageProc(HWND hWnd,
  1876.                                       UINT uMsg,
  1877.                                       LPPROPSHEETPAGE ppsp)
  1878. {
  1879.     return TRUE;
  1880. }
  1881.  
  1882.  
  1883. #ifdef DISABLE_PROTOCOLS_TO_PHYSICAL
  1884.  
  1885. // ----------------------------------------------------------------------
  1886. //
  1887. // Function:  CMuxNotify::EnableBindings
  1888. //
  1889. // Purpose:   Enable/Disable the bindings of other protocols to 
  1890. //            the physical adapter.
  1891. //
  1892. // Arguments:
  1893. //            IN pnccAdapter: Pointer to the physical adapter.
  1894. //            IN bEnable: TRUE/FALSE to enable/disable respectively.
  1895. //
  1896. // Returns:   None.
  1897. //
  1898. // Notes:
  1899. //
  1900.  
  1901. VOID CMuxNotify::EnableBindings (INetCfgComponent *pnccAdapter,
  1902.                                  BOOL bEnable)
  1903. {
  1904.     IEnumNetCfgBindingPath      *pencbp;
  1905.     INetCfgBindingPath          *pncbp;
  1906.     HRESULT                     hr;
  1907.   
  1908.     TraceMsg( L"-->CMuxNotify::EnableBindings.\n" );
  1909.  
  1910.  
  1911.     //
  1912.     // Get the binding path enumerator.
  1913.     //
  1914.  
  1915.     hr = HrGetBindingPathEnum( pnccAdapter,
  1916.                                EBP_ABOVE,
  1917.                                &pencbp );
  1918.     if ( hr == S_OK ) {
  1919.  
  1920.         hr = HrGetBindingPath( pencbp,
  1921.                                &pncbp );
  1922.  
  1923.         //
  1924.         // Traverse each binding path.
  1925.         //
  1926.  
  1927.         while( hr == S_OK ) {
  1928.  
  1929.             //
  1930.             // If our protocol does exist in the binding path then,
  1931.             // disable it.
  1932.             //
  1933.  
  1934.             if ( !IfExistMux(pncbp) ) {
  1935.  
  1936.                 pncbp->Enable( bEnable );
  1937.             }
  1938.  
  1939.             ReleaseObj( pncbp );
  1940.  
  1941.             hr = HrGetBindingPath( pencbp,
  1942.                                    &pncbp );
  1943.         }
  1944.  
  1945.         ReleaseObj( pencbp );
  1946.     }
  1947.     else {
  1948.         TraceMsg( L"   Couldn't get the binding path enumerator, "
  1949.                   L"bindings will not be %s.\n",
  1950.                   bEnable ? L"enabled" : L"disabled" );
  1951.     }
  1952.  
  1953.     TraceMsg( L"<--CMuxNotify::EnableBindings.\n" );
  1954.  
  1955.     return;
  1956. }
  1957.  
  1958. // ----------------------------------------------------------------------
  1959. //
  1960. // Function:  CMuxNotify::IfExistMux
  1961. //
  1962. // Purpose:   Determine if a given binding path contains our protocol.
  1963. //
  1964. // Arguments:
  1965. //            IN pncbp: Pointer to the binding path.
  1966. //
  1967. // Returns:   TRUE if our protocol exists, otherwise FALSE.
  1968. //
  1969. // Notes:
  1970. //
  1971.  
  1972. BOOL CMuxNotify::IfExistMux (INetCfgBindingPath *pncbp)
  1973. {
  1974.     IEnumNetCfgBindingInterface *pencbi;
  1975.     INetCfgBindingInterface     *pncbi;
  1976.     INetCfgComponent            *pnccUpper;
  1977.     LPWSTR                      lpszIdUpper;
  1978.     HRESULT                     hr;
  1979.     BOOL                        bExist = FALSE;
  1980.  
  1981.     TraceMsg( L"-->CMuxNotify::IfExistMux.\n" );
  1982.  
  1983.     //
  1984.     // Get the binding interface enumerator.
  1985.     //
  1986.  
  1987.     hr = HrGetBindingInterfaceEnum( pncbp,
  1988.                                   &pencbi );
  1989.  
  1990.     if ( hr == S_OK ) {
  1991.  
  1992.         //
  1993.         // Traverse each binding interface.
  1994.         //
  1995.  
  1996.         hr = HrGetBindingInterface( pencbi,
  1997.                                     &pncbi );
  1998.  
  1999.         while( !bExist && (hr == S_OK) ) {
  2000.  
  2001.             //
  2002.             // Is the upper component our protocol?
  2003.             //
  2004.  
  2005.             hr = pncbi->GetUpperComponent( &pnccUpper );
  2006.  
  2007.             if ( hr == S_OK ) {
  2008.  
  2009.                 hr = pnccUpper->GetId( &lpszIdUpper );
  2010.  
  2011.                 if ( hr == S_OK ) {
  2012.  
  2013.                     bExist = !_wcsicmp( lpszIdUpper, c_szMuxProtocol );
  2014.  
  2015.                     CoTaskMemFree( lpszIdUpper );
  2016.                 }
  2017.                 else {
  2018.                     TraceMsg( L"   Failed to get the upper component of the interface.\n" );
  2019.                 }
  2020.  
  2021.                 ReleaseObj( pnccUpper );
  2022.             }
  2023.             else {
  2024.                 TraceMsg( L"   Failed to get the upper component of the interface.\n" );
  2025.             }
  2026.  
  2027.             ReleaseObj( pncbi );
  2028.  
  2029.             if ( !bExist ) {
  2030.                 hr = HrGetBindingInterface( pencbi,
  2031.                                             &pncbi );
  2032.             }
  2033.         }
  2034.  
  2035.         ReleaseObj( pencbi );
  2036.     }
  2037.     else {
  2038.         TraceMsg( L"   Couldn't get the binding interface enumerator.\n" );
  2039.     }
  2040.  
  2041.     TraceMsg( L"<--CMuxNotify::IfExistMux(BOOL = %x).\n",
  2042.             bExist );
  2043.  
  2044.     return bExist;
  2045. }
  2046.  
  2047. // ----------------------------------------------------------------------
  2048. //
  2049. // Function:  CMuxNotify::HrGetBindingPathEnum
  2050. //
  2051. // Purpose:   Returns the binding path enumerator.
  2052. //
  2053. // Arguments:
  2054. //            IN  pnccAdapter  : Pointer to the physical adapter.
  2055. //            IN  dwBindingType: Type of binding path enumerator.
  2056. //            OUT ppencbp      : Pointer to the binding path enumerator.
  2057. //
  2058. // Returns:   S_OK on success, otherwise an error code.
  2059. //
  2060. // Notes:
  2061. //
  2062.  
  2063. HRESULT CMuxNotify::HrGetBindingPathEnum (
  2064.                                      INetCfgComponent *pnccAdapter,
  2065.                                      DWORD dwBindingType,
  2066.                                      IEnumNetCfgBindingPath **ppencbp)
  2067. {
  2068.     INetCfgComponentBindings *pnccb = NULL;
  2069.     HRESULT                  hr;
  2070.  
  2071.     *ppencbp = NULL;
  2072.  
  2073.     hr = pnccAdapter->QueryInterface( IID_INetCfgComponentBindings,
  2074.                                (PVOID *)&pnccb );
  2075.  
  2076.     if ( hr == S_OK ) {
  2077.         hr = pnccb->EnumBindingPaths( dwBindingType,
  2078.                                       ppencbp );
  2079.  
  2080.         ReleaseObj( pnccb );
  2081.     }
  2082.  
  2083.     return hr;
  2084. }
  2085.  
  2086. // ----------------------------------------------------------------------
  2087. //
  2088. // Function:  CMuxNotify::HrGetBindingPath
  2089. //
  2090. // Purpose:   Returns a binding path.
  2091. //
  2092. // Arguments:
  2093. //            IN  pencbp  : Pointer to the binding path enumerator.
  2094. //            OUT ppncbp  : Pointer to the binding path.
  2095. //
  2096. // Returns:   S_OK on success, otherwise an error code.
  2097. //
  2098. // Notes:
  2099. //
  2100.  
  2101. HRESULT CMuxNotify::HrGetBindingPath (IEnumNetCfgBindingPath *pencbp,
  2102.                                       INetCfgBindingPath **ppncbp)
  2103. {
  2104.     ULONG   ulCount;
  2105.     HRESULT hr;
  2106.  
  2107.     *ppncbp = NULL;
  2108.  
  2109.     hr = pencbp->Next( 1,
  2110.                        ppncbp,
  2111.                        &ulCount );
  2112.  
  2113.     return hr;
  2114. }
  2115.  
  2116. // ----------------------------------------------------------------------
  2117. //
  2118. // Function:  CMuxNotify::HrGetBindingInterfaceEnum
  2119. //
  2120. // Purpose:   Returns the binding interface enumerator.
  2121. //
  2122. // Arguments:
  2123. //            IN  pncbp  : Pointer to the binding path.
  2124. //            OUT ppencbi: Pointer to the binding path enumerator.
  2125. //
  2126. // Returns:   S_OK on success, otherwise an error code.
  2127. //
  2128. // Notes:
  2129. //
  2130.  
  2131. HRESULT CMuxNotify::HrGetBindingInterfaceEnum (
  2132.                                      INetCfgBindingPath *pncbp,
  2133.                                      IEnumNetCfgBindingInterface **ppencbi)
  2134. {
  2135.     HRESULT hr;
  2136.  
  2137.     *ppencbi = NULL;
  2138.  
  2139.     hr = pncbp->EnumBindingInterfaces( ppencbi );
  2140.  
  2141.     return hr;
  2142. }
  2143.  
  2144. // ----------------------------------------------------------------------
  2145. //
  2146. // Function:  CMuxNotify::HrGetBindingInterface
  2147. //
  2148. // Purpose:   Returns a binding interface.
  2149. //
  2150. // Arguments:
  2151. //            IN  pencbi  : Pointer to the binding interface enumerator.
  2152. //            OUT ppncbi  : Pointer to the binding interface.
  2153. //
  2154. // Returns:   S_OK on success, otherwise an error code.
  2155. //
  2156. // Notes:
  2157. //
  2158.  
  2159. HRESULT CMuxNotify::HrGetBindingInterface (
  2160.                                      IEnumNetCfgBindingInterface *pencbi,
  2161.                                      INetCfgBindingInterface **ppncbi)
  2162. {
  2163.     ULONG   ulCount;
  2164.     HRESULT hr;
  2165.  
  2166.     *ppncbi = NULL;
  2167.  
  2168.     hr = pencbi->Next( 1,
  2169.                        ppncbi,
  2170.                        &ulCount );
  2171.  
  2172.     return hr;
  2173. }
  2174.  
  2175. #endif
  2176.  
  2177.  
  2178.