/*****************************************************************************
* Copyright (c) 1990-98 Digi International Inc., All Rights Reserved
* 
* This software contains proprietary and confidential information of Digi
* International Inc.  By accepting transfer of this copy, Recipient agrees
* to retain this software in confidence, to prevent disclosure to others,
* and to make no use of this software other than that for which it was
* delivered.  This is an unpublished copyrighted work of Digi International
* Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly
* prohibited.
* 
* Restricted Rights Legend
*
* Use, duplication, or disclosure by the Government is subject to
* restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in
* Technical Data and Computer Software clause at DFARS 252.227-7031 or
* subparagraphs (c)(1) and (2) of the Commercial Computer Software -
* Restricted Rights at 48 CFR 52.227-19, as applicable.
*
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
*
*****************************************************************************/


// AdapterHouston.cpp: implementation of the CAdapterHouston class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "AdapterHouston.h"
#include "ObjectFactory.h"
#include "DetectPCI.h"
#include "ModemCCDisplayNameMap.h"
#if defined NT5
#include "ProtocolDisplayNameMap.h"
#include "PropProtocol.h"
#endif // #if defined NT5

#include "Resource.h"


#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNAMIC(CAdapterHouston, CAdapter)

CAdapterHouston::CAdapterHouston(HKEY const hKeyRoot, CString const & strRegPath, CConfigObject const * const pParent) : CAdapter(hKeyRoot, strRegPath, pParent)
{
   try
   {
      // Get parameters
      AffirmThrow(GetParameters());

      if (m_dwModemCC == 0)
      {
         // Check for E1 type
         BOOL fE1 =
            (GetIdentity() == DXB_REGVAL_ADAPTER_ENUM_HOUSTON_E1_SINGLE) ||
            (GetIdentity() == DXB_REGVAL_ADAPTER_ENUM_HOUSTON_E1_DUAL) ||
            (GetIdentity() == DXB_REGVAL_ADAPTER_ENUM_HOUSTON_E1_SINGLE_CPCI) ||
            (GetIdentity() == DXB_REGVAL_ADAPTER_ENUM_HOUSTON_E1_DUAL_CPCI)
            ;

         m_dwModemCC = fE1 ? COUNTRY_CODE_GERMANY : COUNTRY_CODE_UNITED_STATES;
      }

      // Set what we can do
      SetAbility(CConfigObject::DOPROPERTIES);

      // Get our static config data
      AffirmThrow(GetConfigData());

      // Init wiz mode stuff
      m_WizModemCC.Construct(CPageModemCC::WIZARD, this, WP_MODEMCC);
      m_WizModemCC.Init(m_adwModemCCsAllowed);

#if defined NT5
		m_pwpProtocol = NULL;
#endif // #if defined NT5

   }
   catch (CAffirmException ae)
   {
   }
}

CAdapterHouston::~CAdapterHouston()
{
   try
   {
#if defined NT5
      if (NULL != m_pwpProtocol)
      {
         delete m_pwpProtocol;
         m_pwpProtocol = NULL;
      }
#endif // #if defined NT5
   }
   catch (CAffirmException ae)
   {
   }
}

#ifndef NT5
BOOL CAdapterHouston::GetPCIInfoFromAdapterInSlot(SHWResources & hwNewResources)
{
   BOOL fSuccess = FALSE;

   try
   {
      hwNewResources = m_hwResources;

      DIGI_PCI_DATA pciData = {0};
      if (DetectPCI(m_hwResources.busSpecific.Pci.dwBusNumber, m_hwResources.busSpecific.Pci.dwSlotNumber, &pciData))
      {
         AffirmThrow(hwNewResources.busSpecific.Pci.dwBusNumber == pciData.BusNumber);
         AffirmThrow(hwNewResources.busSpecific.Pci.dwSlotNumber == pciData.SlotNumber);
         hwNewResources.busSpecific.Pci.dwVendorID    = pciData.VendorId;
         hwNewResources.busSpecific.Pci.dwPciID       = pciData.DeviceId;
         hwNewResources.busSpecific.Pci.dwSubVendorID = pciData.SubVendorId;
         hwNewResources.busSpecific.Pci.dwSubPciID    = pciData.SubSystemId;
         hwNewResources.busSpecific.Pci.dwRevision    = pciData.RevisionId;
      }

      fSuccess = TRUE;
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

BOOL CAdapterHouston::IsAdpaterInSlotCompatible(SHWResources const & hwNewResources)
{
   BOOL fCompatible = FALSE;

   try
   {
      switch (hwNewResources.busSpecific.Pci.dwVendorID)
      {
         case DIGI_PCI_VENDORID:
         case PATTON_PCI_VENDORID:
         case IBM_PCI_VENDORID:
            break;
         default: AffirmThrow(FALSE); break;
      }

      switch (hwNewResources.busSpecific.Pci.dwPciID)
      {
         case DIGI_PCI_DEVICEID_HOUSTON:
         case DIGI_CPCI_DEVICEID_HOUSTON:
         case IBM_PCI_DEVICEID_HOUSTON:
            break;
         default: AffirmThrow(FALSE); break;
      }

      switch (hwNewResources.busSpecific.Pci.dwSubPciID)
      {
         case DIGI_PCI_SUBDEVICEID_HOUSTON_T1_SINGLE:
         case DIGI_PCI_SUBDEVICEID_HOUSTON_T1_DUAL:
         case DIGI_CPCI_SUBDEVICEID_HOUSTON_T1_SINGLE:
         case DIGI_CPCI_SUBDEVICEID_HOUSTON_T1_DUAL:
         case IBM_PCI_SUBDEVICEID_HOUSTON_T1_SINGLE:
         case IBM_PCI_SUBDEVICEID_HOUSTON_T1_DUAL:
         {
            switch (m_hwResources.busSpecific.Pci.dwSubPciID)
            {
               case DIGI_PCI_SUBDEVICEID_HOUSTON_T1_SINGLE:
               case DIGI_PCI_SUBDEVICEID_HOUSTON_T1_DUAL:
               case DIGI_CPCI_SUBDEVICEID_HOUSTON_T1_SINGLE:
               case DIGI_CPCI_SUBDEVICEID_HOUSTON_T1_DUAL:
               case IBM_PCI_SUBDEVICEID_HOUSTON_T1_SINGLE:
               case IBM_PCI_SUBDEVICEID_HOUSTON_T1_DUAL:
               {
                  fCompatible = TRUE;
                  break;
               }
               default: AffirmThrow(FALSE); break;
            }
            break;
         }

         case DIGI_PCI_SUBDEVICEID_HOUSTON_E1_SINGLE:
         case DIGI_PCI_SUBDEVICEID_HOUSTON_E1_DUAL:
         case DIGI_CPCI_SUBDEVICEID_HOUSTON_E1_SINGLE:
         case DIGI_CPCI_SUBDEVICEID_HOUSTON_E1_DUAL:
         case IBM_PCI_SUBDEVICEID_HOUSTON_E1_SINGLE:
         case IBM_PCI_SUBDEVICEID_HOUSTON_E1_DUAL:
         {
            switch (m_hwResources.busSpecific.Pci.dwSubPciID)
            {
               case DIGI_PCI_SUBDEVICEID_HOUSTON_E1_SINGLE:
               case DIGI_PCI_SUBDEVICEID_HOUSTON_E1_DUAL:
               case DIGI_CPCI_SUBDEVICEID_HOUSTON_E1_SINGLE:
               case DIGI_CPCI_SUBDEVICEID_HOUSTON_E1_DUAL:
               case IBM_PCI_SUBDEVICEID_HOUSTON_E1_SINGLE:
               case IBM_PCI_SUBDEVICEID_HOUSTON_E1_DUAL:
               {
                  fCompatible = TRUE;
                  break;
               }
               default: AffirmThrow(FALSE); break;
            }
            break;
         }

         default: AffirmThrow(FALSE); break;
      }
   }
   catch (CAffirmException ae)
   {
   }

   TRACE("Card in slot is %s\n", (fCompatible) ? TEXT("compatible") : TEXT("incompatible"));
   return fCompatible;
}

enum
{
   NUM_LINES_SINGLE = 1,
   NUM_LINES_DUAL = 2,
};

BOOL CAdapterHouston::ChangeInDaughterCard(SHWResources const & hwNewResources, int & cLineDelta)
{
   BOOL fChange = FALSE;

   try
   {
      cLineDelta = 0;      // this may be negative

      switch (hwNewResources.busSpecific.Pci.dwVendorID)
      {
         case DIGI_PCI_VENDORID:
         case PATTON_PCI_VENDORID:
         case IBM_PCI_VENDORID:
            break;
         default: AffirmThrow(FALSE); break;
      }

      switch (hwNewResources.busSpecific.Pci.dwPciID)
      {
         case DIGI_PCI_DEVICEID_HOUSTON:
         case DIGI_CPCI_DEVICEID_HOUSTON:
         case IBM_PCI_DEVICEID_HOUSTON:
            break;
         default: AffirmThrow(FALSE); break;
      }

      int cMaxLines = 0;
      switch (hwNewResources.busSpecific.Pci.dwSubPciID)
      {
         case DIGI_PCI_SUBDEVICEID_HOUSTON_T1_SINGLE:
         case DIGI_PCI_SUBDEVICEID_HOUSTON_E1_SINGLE:
         case DIGI_CPCI_SUBDEVICEID_HOUSTON_T1_SINGLE:
         case DIGI_CPCI_SUBDEVICEID_HOUSTON_E1_SINGLE:
         case IBM_PCI_SUBDEVICEID_HOUSTON_T1_SINGLE:
         case IBM_PCI_SUBDEVICEID_HOUSTON_E1_SINGLE:
         {
            cMaxLines = NUM_LINES_SINGLE;
            break;
         }

         case DIGI_PCI_SUBDEVICEID_HOUSTON_T1_DUAL:
         case DIGI_PCI_SUBDEVICEID_HOUSTON_E1_DUAL:
         case DIGI_CPCI_SUBDEVICEID_HOUSTON_T1_DUAL:
         case DIGI_CPCI_SUBDEVICEID_HOUSTON_E1_DUAL:
         case IBM_PCI_SUBDEVICEID_HOUSTON_T1_DUAL:
         case IBM_PCI_SUBDEVICEID_HOUSTON_E1_DUAL:
         {
            cMaxLines = NUM_LINES_DUAL;
            break;
         }

         default: AffirmThrow(FALSE); break;
      }

      cLineDelta = cMaxLines - m_cLines;
      fChange = (cLineDelta != 0);
   }
   catch (CAffirmException ae)
   {
   }

   TRACE("Daughter card %s\n", ((!fChange) ? TEXT("unchanged") : 
                                ((cLineDelta > 0) ? TEXT("added") : TEXT("removed"))));
   return fChange;
}

BOOL CAdapterHouston::DetectHWChange(BOOL & fHWChanged, BOOL & fRunWizard)
{
   BOOL fSuccess = TRUE;

   try
   {
      SHWResources hwNewResources;

      AffirmThrow(GetPCIInfoFromAdapterInSlot(hwNewResources));
 
      if (IsAdpaterInSlotCompatible(hwNewResources))
      {
         int cLineDelta = 0;

         if (ChangeInDaughterCard(hwNewResources, cLineDelta))
         {
            fHWChanged = TRUE;

            if (cLineDelta > 0)     // added daughter card
            {
               AffirmThrow(cLineDelta == NUM_LINES_SINGLE);
               AffirmThrow(m_cLines == NUM_LINES_SINGLE);
               AffirmThrow(GetChildCount() == NUM_LINES_SINGLE);

               TRACE("Looks like someone added a daughter card\n");

               // create the new line
               m_cLines++;
               AddChild();

               // since houston lines cannot be disabled anymore
               // we'll simply copy the parameters from line 1
               AffirmThrow(m_apChildren[0] != NULL);
               AffirmThrow(m_apChildren[1] != NULL);
               AffirmThrow(m_apChildren[1]->CopyParameters(m_apChildren[0]));

               // make sure params are written to registry
               AffirmThrow(SetParameters());

               // see if user wants to run wizard now
               CString strQuestion;
               AffirmThrow(strQuestion.LoadString(IDS_RunWizardBecauseOfNewLine));
               fRunWizard = (::MessageBox(::GetDesktopWindow(), strQuestion, GetDisplayName(), MB_YESNO | MB_ICONQUESTION) == IDYES);

               TRACE("The user %s want to run the install wizard for the new line\n", (fRunWizard) ? TEXT("does") : TEXT("doesn't"));
            }
            else                    // remove daughter card
            {
               AffirmThrow(cLineDelta == -NUM_LINES_SINGLE);
               AffirmThrow(m_cLines == NUM_LINES_DUAL);
               AffirmThrow(GetChildCount() == NUM_LINES_DUAL);

               TRACE("Looks like someone removed the daughter card\n");

#if defined(ALLOW_REMOVAL_OF_LINE)
               if (AfxMessageBox(IDS_PermanentlyRemoveLine, MB_YESNO | MB_ICONQUESTION) == IDYES)
               {
                  TRACE("Premanently removing line 1\n");

                  CLine * pLineToDelete = (CLine *)GetChild(NUM_LINES_SINGLE);
                  AffirmThrow(pLineToDelete != NULL);

                  AffirmThrow(DeleteChild(pLineToDelete));

                  m_cLines--;

                  AffirmThrow(SetParameters());
               }
#endif

               fRunWizard = FALSE;
            }
         }
         else
         {
            AffirmThrow(cLineDelta == 0);

            TRACE("Looks like adapter hasn't changed since the last time we saw it\n");

            fHWChanged = FALSE;
            fRunWizard = FALSE;
         }

         fSuccess = TRUE;
      }
      else
      {
         // I'm not really sure what to do here
         fHWChanged = TRUE;
         fRunWizard = FALSE;
      }
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

#endif // #ifndef NT5

//////////////////////////////////////////////////////////////////////
// Get/Set parameters
//////////////////////////////////////////////////////////////////////

BOOL CAdapterHouston::GetParameters(void)
{
   BOOL fSuccess = FALSE;

   try
   {

#if defined NT5
      // NOTE: NOTE: This assumes a lot!
      // Since the Line objects aren't created yet, we get this from the registry early
      // The value should have been set by the installer if that's where we are
      // Line indexes must be zero based
      // The first line key must be present (0)
      // If more than one line, the protocols must be the same (for NT5 we impose this rule)
      m_strProtocol = TEXT("");
      HKEY hLineKey;
      if (RegOpenKey(m_hKey, TEXT("0"), &hLineKey))
      {
         AffirmThrow(RegReadStrValue(hLineKey, DXB_REGVAL_PROTOCOL, m_strProtocol));
      }
      RegCloseKey(hLineKey);
#endif // #if defined NT5

      AffirmThrow(RegReadDWordValue(m_hKey, DXB_REGVAL_MODEM_NATIONALITY, &m_dwModemCC));
      fSuccess = TRUE;
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

BOOL CAdapterHouston::SetParameters(void)
{
   BOOL fSuccess = FALSE;

   try
   {
      AffirmThrow(CAdapter::SetParameters());

#if defined NT5
      // NOTE: NOTE: The lines will take care of writing the protocol parameter
      // The adapter only needs to write the ISDN Wiz bit
      // If we're not PRI (ISDN) then we need to disable MS's ISDN Wiz

      // Get the registry entry that specifies our adapter instance,
      // it's one level up from here...
      // But, use the value "RegInstance" that's at the Parameters level (m_hKey)
      CString strRegInstance;
      CString strInstanceKey;
      AffirmThrow(RegReadStrValue(m_hKey, DXB_REGVAL_REGINSTANCE, strRegInstance));
      strInstanceKey.Format("%s%s", DXB_REGCLASS_VALUE, strRegInstance);
      TRACE("CAdapterHouston::SetParameters(): Opening %s\n", strInstanceKey);
      HKEY hAdapterInstance;
      if (RegOpenKey(HKEY_LOCAL_MACHINE, strInstanceKey, &hAdapterInstance))
      {
		 BOOL fShowIsdn = ( (DXB_REGVAL_PROTOCOL_ENUM_E1 == m_strProtocol) || (DXB_REGVAL_PROTOCOL_ENUM_PRI == m_strProtocol));
         TRACE("CAdapterHouston::SetParameters(): Writing  ShowIsdnPages value:%d\n", fShowIsdn ? 1 : 0);
         AffirmThrow(RegWriteDWordValue(  hAdapterInstance,
                                          TEXT("ShowIsdnPages"),
                                          (fShowIsdn ? 1 : 0)));
         RegCloseKey(hAdapterInstance);
      }
#endif // #if defined NT5

      AffirmThrow(RegWriteDWordValue(m_hKey, DXB_REGVAL_MODEM_NATIONALITY, m_dwModemCC));
      fSuccess = TRUE;
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

//////////////////////////////////////////////////////////////////////
// Config data
//////////////////////////////////////////////////////////////////////

BOOL CAdapterHouston::GetConfigData(void)
{
   BOOL fSuccess = FALSE;

   try
   {
      // NOTE:
      //    This next section could be stored in the registry, but I couldn't
      //    figure out a cool automated way to get the list of allowed modem ccs there.

      static DWORD const adwModemCCsT1[] = HOUSTON_T1_DRV_CC_LIST_INIT;
      static DWORD const adwModemCCsE1[] = HOUSTON_E1_DRV_CC_LIST_INIT;

      DWORD const * adwModemCCs = NULL;
      int cModemCCs = 0;

      // Check for E1 type
      BOOL fE1 =
         (GetIdentity() == DXB_REGVAL_ADAPTER_ENUM_HOUSTON_E1_SINGLE) ||
         (GetIdentity() == DXB_REGVAL_ADAPTER_ENUM_HOUSTON_E1_DUAL) ||
         (GetIdentity() == DXB_REGVAL_ADAPTER_ENUM_HOUSTON_E1_SINGLE_CPCI) ||
         (GetIdentity() == DXB_REGVAL_ADAPTER_ENUM_HOUSTON_E1_DUAL_CPCI)
         ;

      //[jjl]070901 This appears to be a bad thing -- we'll lose any setting
      //            retrieved from the registry by ::GetParameters()
      //m_dwModemCC = fE1 ? COUNTRY_CODE_GERMANY : COUNTRY_CODE_UNITED_STATES;
      if (fE1)
      {
         adwModemCCs = adwModemCCsE1;
         cModemCCs = ElementCount(adwModemCCsE1);
      }
      else
      {
         adwModemCCs = adwModemCCsT1;
         cModemCCs = ElementCount(adwModemCCsT1);
      }

      AffirmThrow(adwModemCCs != NULL);
      AffirmThrow(cModemCCs > 0);

      m_adwModemCCsAllowed.RemoveAll();

      for (int i = 0; i < cModemCCs; i++)
      {
         m_adwModemCCsAllowed.Add(adwModemCCs[i]);
      }

#if defined NT5
      // Get the line protocols available for this kind of adapter
      CString strConfigDataRegPath;
      AffirmThrow(BuildConfigDataRegPath(strConfigDataRegPath));
      TRACE("CAdapterHouston::GetConfigData(): strConfigDataRegPath:%s\n",strConfigDataRegPath);
      HKEY hConfigData = NULL;
      AffirmThrow(RegOpenKey(HKEY_LOCAL_MACHINE, strConfigDataRegPath, &hConfigData));
      AffirmThrow(hConfigData != NULL);
      AffirmThrow(RegReadMultiStrValue(hConfigData, DXB_REGVAL_PROTOCOLS_ALLOWED, m_astrProtocolsAllowed));
      RegCloseKey(hConfigData);
#endif // #if defined NT5

      fSuccess = TRUE;
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

//////////////////////////////////////////////////////////////////////
// Wizard config methods
//////////////////////////////////////////////////////////////////////

BOOL CAdapterHouston::AddWizardPages(CConfigWizSheet * const pSheet)
{
   BOOL fSuccess = FALSE;

   try
   {
      AffirmThrow(pSheet != NULL);

#if defined(_DEBUG)
      if ((m_pwsSheet != NULL) && (m_pwsSheet != pSheet))
         TRACE("AddWizardPages() called for different sheet!\n");
#endif

      AffirmThrow(CAdapter::AddWizardPages(pSheet));

      fSuccess = TRUE;
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

BOOL CAdapterHouston::RemoveWizardPages(CConfigWizSheet * const pSheet)
{
   BOOL fSuccess = FALSE;

   try
   {
      AffirmThrow(pSheet != NULL);

#if defined NT5
      if (NULL != m_pwpProtocol)
      {
         pSheet->RemovePage(m_pwpProtocol);
      }
#endif // #if defined NT5

      pSheet->RemovePage(&m_WizModemCC);

      AffirmThrow(CAdapter::RemoveWizardPages(pSheet));

      fSuccess = TRUE;
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

BOOL CAdapterHouston::HandleWizWelcome(void)
{
   BOOL fSuccess = FALSE;

   try
   {
      AffirmThrow(m_pwsSheet != NULL);

#if defined NT5
      // Create, configure and add the protocol wiz page
		if (m_pwpProtocol == NULL)
		{
			CString strTitle;
			CString strInstruction;

			AffirmThrow(strTitle.LoadString(IDS_Title_LineProtocol));
			AffirmThrow(strInstruction.LoadString(IDS_Instruction_LineProtocol));

			strTitle = GetDisplayName() + TEXT(" - ") + strTitle;

			m_pwpProtocol = new CWizPageComboBox(this, WP_PROTOCOL, strTitle, strInstruction);
			AffirmThrow(m_pwpProtocol != NULL);

			m_pwpProtocol->SetHelpID(IDH_WizPageLineProtocol);

			int iDefaultProtocol = 0;
			CProtocolDisplayNameMap mapProtocolDisplayNames;
			CStringArray astrProtocolDisplayNames;

			for (int iAllowed = 0; iAllowed < m_astrProtocolsAllowed.GetSize(); iAllowed++)
			{
				if (m_strProtocol == m_astrProtocolsAllowed[iAllowed]) iDefaultProtocol = iAllowed;

				astrProtocolDisplayNames.SetAtGrow(iAllowed, mapProtocolDisplayNames[m_astrProtocolsAllowed[iAllowed]]);
				AffirmThrow(!astrProtocolDisplayNames[iAllowed].IsEmpty());
			}

			AffirmThrow(m_pwpProtocol->SetValues(astrProtocolDisplayNames, iDefaultProtocol));
      }
  		AffirmThrow(m_pwsSheet->InsertPage(m_pwpProtocol));

#else // #if defined NT5
      m_WizModemCC.SetModemCC(m_dwModemCC);

      AffirmThrow(m_pwsSheet->InsertPage(&m_WizModemCC));

      AffirmThrow(CAdapter::HandleWizWelcome());
#endif // #if defined NT5

      fSuccess = TRUE;
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

#if defined NT5
BOOL CAdapterHouston::HandleWizProtocol(void)
{
   BOOL fSuccess = FALSE;
   // The protocol page finished, need to impose the new protocol on the child lines....
   try
   {
      AffirmThrow(m_pwsSheet != NULL);
      TRACE("CAdapterHouston::HandleWizProtocol()\n");

      int iChoice = m_pwpProtocol->GetChoice();
      m_strProtocol = m_astrProtocolsAllowed[iChoice];

      // We assume that the children are lines here
      // Step through all of them and impose the change
      for (int j = 0; j < m_apChildren.GetSize(); j++)
      {
         AffirmThrow(m_apChildren[j] != NULL);
         CLine * pChild = (CLine *)m_apChildren[j];
         TRACE("CAdapterHouston::HandleWizProtocol(): Switching Line:%d to Protocol:%s\n", j, m_strProtocol);
         AffirmThrow(pChild->SwitchProtocol(m_strProtocol));
      }

      m_WizModemCC.SetModemCC(m_dwModemCC);

      AffirmThrow(m_pwsSheet->InsertPage(&m_WizModemCC));

      fSuccess = TRUE;
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}
#endif // #if defined NT5

BOOL CAdapterHouston::HandleWizModemCC(void)
{
   BOOL fSuccess = FALSE;

   try
   {
      AffirmThrow(m_pwsSheet != NULL);

      m_dwModemCC = m_WizModemCC.GetModemCC();

#if defined NT5
      // For NT5, we need to add our line pages here
      // CAdapter::HandleWizWelcome() ends up doing this...
      AffirmThrow(CAdapter::HandleWizWelcome());
#endif // #if defined NT5

      fSuccess = TRUE;
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

BOOL CAdapterHouston::NextWizardPage(int const nState)
{
   BOOL fSuccess = FALSE;

   try
   {
      switch (nState)
      {
         case WP_WELCOME: AffirmThrow(HandleWizWelcome());                break;
#if defined NT5
         case WP_PROTOCOL: AffirmThrow(HandleWizProtocol());              break;
#endif // #if defined NT5
         case WP_MODEMCC: AffirmThrow(HandleWizModemCC());                break;
         default:         AffirmThrow(CAdapter::NextWizardPage(nState));  break;
      }

      fSuccess = TRUE;
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

//////////////////////////////////////////////////////////////////////
// UI config methods
//////////////////////////////////////////////////////////////////////

CString CAdapterHouston::GetInformationText(void)
{
   CString strInfo = TEXT("");

   try
   {
#if defined NT5
      CString strInfoProtocol = TEXT("");
      CProtocolDisplayNameMap mapProtocolDisplayNames;
      strInfoProtocol.Format(IDS_Information_LineFormat,mapProtocolDisplayNames[m_strProtocol]);
#endif // #if defined NT5
      CString strInfoModem = TEXT("");
      CModemCCDisplayNameMap mapModemCCDisplayNames;
      strInfoModem.Format(IDS_Information_ModemCC, mapModemCCDisplayNames[m_dwModemCC]);
#if defined NT5
      strInfo.Format("%s\n%s",strInfoProtocol, strInfoModem);
#else // #if defined NT5
      strInfo = strInfoModem;
#endif // #if defined NT5

   }
   catch (CAffirmException ae)
   {
   }

   return strInfo;
}

BOOL CAdapterHouston::DoProperties(void)
{
   BOOL fThingsHaveChanged = FALSE;

   try
   {
      CPropertySheet PropSheet(GetDisplayName());
      PropSheet.m_psh.dwFlags |= PSH_NOAPPLYNOW;

#if defined NT5
      // Create and add the Protocol page
      CProtocolDisplayNameMap mapProtocolDisplayNames;
      CStringArray astrProtocolDisplayNames;
      int iDefaultProtocol = 0;
      for (int iAllowed = 0; iAllowed < m_astrProtocolsAllowed.GetSize(); iAllowed++)
      {
         if (m_strProtocol == m_astrProtocolsAllowed[iAllowed]) iDefaultProtocol = iAllowed;
         astrProtocolDisplayNames.SetAtGrow(iAllowed, mapProtocolDisplayNames[m_astrProtocolsAllowed[iAllowed]]);
         AffirmThrow(!astrProtocolDisplayNames[iAllowed].IsEmpty());
      }
      CPropProtocol PropProtocol(IDS_Title_LineProtocol);
      AffirmThrow(PropProtocol.SetValues(astrProtocolDisplayNames, iDefaultProtocol));
      PropSheet.AddPage(&PropProtocol);
#endif // #if defined NT5

      // Create and add the Modems page
      CPageModemCC PropModemCC(CPageModemCC::PROPPAGE);
      PropModemCC.Init(m_adwModemCCsAllowed);
      PropModemCC.SetModemCC(m_dwModemCC);
      PropSheet.AddPage(&PropModemCC);

      // Run the propsheet
      if (PropSheet.DoModal() == IDOK)
      {
#if defined NT5
         int iChoice = PropProtocol.GetChoice();
         m_strProtocol = m_astrProtocolsAllowed[iChoice];
         // We assume that the children are lines here
         // Step through all of them and impose the change
         for (int j = 0; j < m_apChildren.GetSize(); j++)
         {
            AffirmThrow(m_apChildren[j] != NULL);
            CLine * pChild = (CLine *)m_apChildren[j];
            TRACE("CAdapterHouston::DoProperties(): Switching Line:%d to Protocol:%s\n", j, m_strProtocol);
            AffirmThrow(pChild->SwitchProtocol(m_strProtocol));
         }
#endif // #if defined NT5
         m_dwModemCC = PropModemCC.GetModemCC();
         fThingsHaveChanged = TRUE;
      }
   }
   catch (CAffirmException ae)
   {
   }

   return fThingsHaveChanged;
}
