/*****************************************************************************
* Copyright (c) 1990-99 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
*
*****************************************************************************/


// Adapter.cpp: implementation of the CAdapter class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Adapter.h"
#include "ObjectFactory.h"

#include "Resource.h"
#include "ISAResources.h"

#ifdef NT5
#include "DriverServices.h"
#endif

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

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

IMPLEMENT_DYNAMIC(CAdapter, CConfigObject)

CAdapter::CAdapter(HKEY const hKeyRoot, CString const & strRegPath, CConfigObject const * const pParent) : CConfigObject(hKeyRoot, strRegPath, pParent)
{
   // Init wiz mode stuff
   m_pwsSheet = NULL;
   m_pwpWelcome = NULL;
   m_pwpMultiLines = NULL;
   m_pwpDone = NULL;
   m_pwpIsaResources = NULL;
   m_fAskMultiLines = TRUE;
   m_cMaxLogicalChannelsPerLine = 0;
   m_nHasModems = DXB_REGVAL_ASYN_MODEMDEVICE_DEFAULT;
   m_nHasWizard = DXB_REGVAL_HAS_WIZARD_DEFAULT;
   m_ConfigMessage.Empty();

   try
   {
      AffirmThrow(m_hKey != NULL);
      AffirmThrow(pParent == NULL);

      SetType(CConfigObject::ADAPTER);

      AffirmThrow(GetParameters());

      // Solve our identity crisis
      // Add to this table any time a new adapter is added. 
      // Make sure to define the adapter in DigiFwrk.CPP
      // !reworked 050400 [jjl]  No longer need mapping from PCI IDs to Identity
      // !for NT4 PCI since INF now writes Identity for all boards.  This code
      // !changed to map only from Identity to DisplayName.
      static const struct
      {
         TCHAR * pszIdentity;
         UINT nDisplayNameID;
      }
      aAdapterData[] =
      {
         { DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_2,          IDS_DisplayName_ClydeNONCSU },
         { DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_4,          IDS_DisplayName_ClydeNONCSU },
         { DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_603_2,      IDS_DisplayName_ClydeNONCSU603 },
         { DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_603_4,      IDS_DisplayName_ClydeNONCSU603 },
         { DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_2,          IDS_DisplayName_ClydeNONCSU },
         { DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_4,          IDS_DisplayName_ClydeNONCSU },
         { DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_603_2,      IDS_DisplayName_ClydeNONCSU603 },
         { DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_603_4,      IDS_DisplayName_ClydeNONCSU603 },
         { DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_2,          IDS_DisplayName_ClydeNONCSU },
         { DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_4,          IDS_DisplayName_ClydeNONCSU },
         { DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_603_2,      IDS_DisplayName_ClydeNONCSU603 },
         { DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_603_4,      IDS_DisplayName_ClydeNONCSU603 },
         { DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_2,          IDS_DisplayName_ClydeNONCSU },
         { DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_4,          IDS_DisplayName_ClydeNONCSU },
         { DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_603_2,      IDS_DisplayName_ClydeNONCSU603 },
         { DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_603_2,      IDS_DisplayName_ClydeNONCSU603 },
         { DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_2,          IDS_DisplayName_ClydeNONCSU },
         { DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_603_4,      IDS_DisplayName_ClydeNONCSU603 },

         { DXB_REGVAL_ADAPTER_ENUM_SYNC570_PCI_2PORT,       IDS_DisplayName_Sync570_PCI_2 },
         { DXB_REGVAL_ADAPTER_ENUM_SYNC570_PCI_4PORT,       IDS_DisplayName_Sync570_PCI_4 },
         { DXB_REGVAL_ADAPTER_ENUM_SYNC570_ISA_2PORT,       IDS_DisplayName_Sync570_ISA_2 },
         { DXB_REGVAL_ADAPTER_ENUM_SYNC570_ISA_4PORT,       IDS_DisplayName_Sync570_ISA_4 },

         { DXB_REGVAL_ADAPTER_ENUM_HOUSTON_T1_SINGLE,       IDS_DisplayName_DigiHoustonT1Single },
         { DXB_REGVAL_ADAPTER_ENUM_HOUSTON_T1_DUAL,         IDS_DisplayName_DigiHoustonT1Dual },
         { DXB_REGVAL_ADAPTER_ENUM_HOUSTON_E1_SINGLE,       IDS_DisplayName_DigiHoustonE1Single },
         { DXB_REGVAL_ADAPTER_ENUM_HOUSTON_E1_DUAL,         IDS_DisplayName_DigiHoustonE1Dual },
         { DXB_REGVAL_ADAPTER_ENUM_HOUSTON_T1_SINGLE_CPCI,  IDS_DisplayName_DigicPciHoustonT1Single },
         { DXB_REGVAL_ADAPTER_ENUM_HOUSTON_T1_DUAL_CPCI,    IDS_DisplayName_DigicPciHoustonT1Dual },
         { DXB_REGVAL_ADAPTER_ENUM_HOUSTON_E1_SINGLE_CPCI,  IDS_DisplayName_DigicPciHoustonE1Single },
         { DXB_REGVAL_ADAPTER_ENUM_HOUSTON_E1_DUAL_CPCI,    IDS_DisplayName_DigicPciHoustonE1Dual },

         { DXB_REGVAL_ADAPTER_ENUM_LONDON_ST,               IDS_DisplayName_DigiLondonST },
         { DXB_REGVAL_ADAPTER_ENUM_LONDON_U,                IDS_DisplayName_DigiLondonU },

         // For W2K, we preserve the Chaska's DAA type in the identity,
         // for NT4, the PCI ID is interrogated at a later time
#if defined NT5
         { DXB_REGVAL_ADAPTER_ENUM_CHASKA_40,               IDS_DisplayName_DigiChaska4 },
         { DXB_REGVAL_ADAPTER_ENUM_CHASKA_41,               IDS_DisplayName_DigiChaska4 },
         { DXB_REGVAL_ADAPTER_ENUM_CHASKA_42,               IDS_DisplayName_DigiChaska4 },
         { DXB_REGVAL_ADAPTER_ENUM_CHASKA_43,               IDS_DisplayName_DigiChaska4 },
         { DXB_REGVAL_ADAPTER_ENUM_CHASKA_44,               IDS_DisplayName_DigiChaska4 },
         { DXB_REGVAL_ADAPTER_ENUM_CHASKA_45,               IDS_DisplayName_DigiChaska4 },
         { DXB_REGVAL_ADAPTER_ENUM_CHASKA_80,               IDS_DisplayName_DigiChaska8 },
         { DXB_REGVAL_ADAPTER_ENUM_CHASKA_81,               IDS_DisplayName_DigiChaska8 },
         { DXB_REGVAL_ADAPTER_ENUM_CHASKA_82,               IDS_DisplayName_DigiChaska8 },
         { DXB_REGVAL_ADAPTER_ENUM_CHASKA_83,               IDS_DisplayName_DigiChaska8 },
         { DXB_REGVAL_ADAPTER_ENUM_CHASKA_84,               IDS_DisplayName_DigiChaska8 },
         { DXB_REGVAL_ADAPTER_ENUM_CHASKA_85,               IDS_DisplayName_DigiChaska8 },
#else // #if defined NT5
         { DXB_REGVAL_ADAPTER_ENUM_CHASKA_4,                IDS_DisplayName_DigiChaska4 },
         { DXB_REGVAL_ADAPTER_ENUM_CHASKA_8,                IDS_DisplayName_DigiChaska8 },
#endif // #if defined NT5

         { DXB_REGVAL_ADAPTER_ENUM_PRIME_T1_PCI,            IDS_DisplayName_PrimeT1 },
         { DXB_REGVAL_ADAPTER_ENUM_PRIME_E1_PCI,            IDS_DisplayName_PrimeE1 },
         { DXB_REGVAL_ADAPTER_ENUM_PRIME_ISA,               IDS_DisplayName_PrimeT1ISA },
         { DXB_REGVAL_ADAPTER_ENUM_ACCELEPORT_2R_2000,      IDS_DisplayName_AccelePort2r2000 },
         { DXB_REGVAL_ADAPTER_ENUM_ACCELEPORT_4R_2000,      IDS_DisplayName_AccelePort4r2000 },
         { DXB_REGVAL_ADAPTER_ENUM_ACCELEPORT_8R_2000,      IDS_DisplayName_AccelePort8r2000 },
         { DXB_REGVAL_ADAPTER_ENUM_ACCELEPORT_16R_2000,     IDS_DisplayName_AccelePort16r2000 },
      };

      TCHAR const * pszIdentity = TEXT("");
      int nDisplayNameID = 0;
      BOOL fAdapterFound = FALSE;

      {
         CString strIdentity = GetIdentity();
		 if ( strIdentity.IsEmpty() )
		 {
			SetUpdateIdenity();
			return;
			
		 }
         AffirmThrow(!strIdentity.IsEmpty());

         for (int i = 0; i < ElementCount(aAdapterData); i++)
         {
            if (strIdentity.CompareNoCase(aAdapterData[i].pszIdentity)==0)
            {
               pszIdentity = aAdapterData[i].pszIdentity;
               nDisplayNameID = aAdapterData[i].nDisplayNameID;
               fAdapterFound = TRUE;
               break;
            }
         }
      }


      AffirmThrow(fAdapterFound);
      SetIdentity(pszIdentity);

      // Set our display name
      CString strDisplayName;
      AffirmThrow(strDisplayName.LoadString(nDisplayNameID));
      SetDisplayName(strDisplayName);

      // Set what we can do
      // In general, properties at the adapter level only involve ISA or EISA params...
      if (m_hwResources.IsIsaOrEisaBus())
         SetAbility(CConfigObject::DOPROPERTIES);
      else
         SetAbility(CConfigObject::NOABILITIES);

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

      // Init our bitmap
      AffirmThrow(m_WizBmp.Load(g_hInstance, IDB_DigiLogo, TRUE));

      // Give birth to our children
      for (int i = 0; i < m_cLines; i++)
      {
         AffirmThrow(AddChild(i));
      }
   }
   catch (CAffirmException ae)
   {
   }

   
}

CAdapter::~CAdapter()
{
   try
   {
      delete m_pwpWelcome;
      delete m_pwpMultiLines;
      delete m_pwpDone;
      delete m_pwpIsaResources;
   }
   catch (CAffirmException ae)
   {
   }
}

/***************************************************************************************************
**
**	CAdapter::SetUpdateIdenity()
**
**	Purpose: There is not a idenity varible in the old NT4 H driver registry.  So updating from
**		the h to j does not work.  If this is the case then this function will determine the ident
**		of the board and set it so that the update prop page will work (Dejones 11/10/00 
**
****************************************************************************************************/
void CAdapter::SetUpdateIdenity()
{
	// Init wiz mode stuff
   m_pwsSheet = NULL;
   m_pwpWelcome = NULL;
   m_pwpMultiLines = NULL;
   m_pwpDone = NULL;
   m_pwpIsaResources = NULL;
   m_fAskMultiLines = TRUE;
   m_cMaxLogicalChannelsPerLine = 0;
   m_nHasModems = DXB_REGVAL_ASYN_MODEMDEVICE_DEFAULT;
   m_nHasWizard = DXB_REGVAL_HAS_WIZARD_DEFAULT;
   m_ConfigMessage.Empty();

   try
   {
      AffirmThrow(m_hKey != NULL);

      SetType(CConfigObject::ADAPTER);

      AffirmThrow(GetParameters());
	static const struct
      {
         DWORD dwVendorID;
         DWORD dwPciID;
         DWORD dwSubPciID;
         TCHAR * pszIdentity;
         UINT nDisplayNameID;
      }
      aAdapterData[] =
      {
         // TODO PATTON: Add Patton PCI ID
         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CLYDE_NON_CSU_2, DIGI_PCI_SUBDEVICEID_CLYDE_NON_CSU_2,
            DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_2, IDS_DisplayName_ClydeNONCSU
         },

         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CLYDE_NON_CSU_4, DIGI_PCI_SUBDEVICEID_CLYDE_NON_CSU_4,
            DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_4, IDS_DisplayName_ClydeNONCSU
         },

         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CLYDE_NON_CSU_603_2, DIGI_PCI_SUBDEVICEID_CLYDE_NON_CSU_603_2,
            DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_603_2, IDS_DisplayName_ClydeNONCSU603
         },

         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CLYDE_NON_CSU_603_4, DIGI_PCI_SUBDEVICEID_CLYDE_NON_CSU_603_4,
            DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_603_4, IDS_DisplayName_ClydeNONCSU603
         },

         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CLYDE_NON_CSU_2, DIGI_PCI_SUBDEVICEID_NONE,
            DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_2, IDS_DisplayName_ClydeNONCSU
         },

         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CLYDE_NON_CSU_4, DIGI_PCI_SUBDEVICEID_NONE,
            DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_4, IDS_DisplayName_ClydeNONCSU
         },

         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CLYDE_NON_CSU_603_2, DIGI_PCI_SUBDEVICEID_NONE,
            DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_603_2, IDS_DisplayName_ClydeNONCSU603
         },

         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CLYDE_NON_CSU_603_4, DIGI_PCI_SUBDEVICEID_NONE,
            DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_603_4, IDS_DisplayName_ClydeNONCSU603
         },

         {
            DIGI_PCI_VENDORID, DIGI_CPCI_DEVICEID_CLYDE_NON_CSU_2, DIGI_CPCI_SUBDEVICEID_CLYDE_NON_CSU_2,
            DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_2, IDS_DisplayName_ClydeNONCSU
         },

         {
            DIGI_PCI_VENDORID, DIGI_CPCI_DEVICEID_CLYDE_NON_CSU_4, DIGI_CPCI_SUBDEVICEID_CLYDE_NON_CSU_4,
            DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_4, IDS_DisplayName_ClydeNONCSU
         },

         {
            DIGI_PCI_VENDORID, DIGI_CPCI_DEVICEID_CLYDE_NON_CSU_603_2, DIGI_CPCI_SUBDEVICEID_CLYDE_NON_CSU_603_2,
            DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_603_2, IDS_DisplayName_ClydeNONCSU603
         },

         {
            DIGI_PCI_VENDORID, DIGI_CPCI_DEVICEID_CLYDE_NON_CSU_603_4, DIGI_CPCI_SUBDEVICEID_CLYDE_NON_CSU_603_4,
            DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_603_4, IDS_DisplayName_ClydeNONCSU603
         },

         {
            DIGI_PCI_VENDORID, DIGI_CPCI_DEVICEID_CLYDE_NON_CSU_2, DIGI_CPCI_SUBDEVICEID_NONE,
            DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_2, IDS_DisplayName_ClydeNONCSU
         },

         {
            DIGI_PCI_VENDORID, DIGI_CPCI_DEVICEID_CLYDE_NON_CSU_4, DIGI_CPCI_SUBDEVICEID_NONE,
            DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_4, IDS_DisplayName_ClydeNONCSU
         },

         {
            DIGI_PCI_VENDORID, DIGI_CPCI_DEVICEID_CLYDE_NON_CSU_603_2, DIGI_CPCI_SUBDEVICEID_NONE,
            DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_603_2, IDS_DisplayName_ClydeNONCSU603
         },

         {
            DIGI_PCI_VENDORID, DIGI_PMC_DEVICEID_CLYDE_NON_CSU_603_2, DIGI_PMC_SUBDEVICEID_CLYDE_NON_CSU_603_2,
            DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_603_2, IDS_DisplayName_ClydeNONCSU603
         },

         {
            DIGI_PCI_VENDORID, DIGI_PMC_DEVICEID_CLYDE_NON_CSU_2, DIGI_PMC_SUBDEVICEID_CLYDE_NON_CSU_2,
            DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_2, IDS_DisplayName_ClydeNONCSU
         },

         {
            DIGI_PCI_VENDORID, DIGI_CPCI_DEVICEID_CLYDE_NON_CSU_603_4, DIGI_CPCI_SUBDEVICEID_NONE,
            DXB_REGVAL_ADAPTER_ENUM_CLYDE_NONCSU_603_4, IDS_DisplayName_ClydeNONCSU603
         },

         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_SYNC570_PCI_2PORT, DIGI_PCI_SUBDEVICEID_SYNC570_PCI_2PORT,
            DXB_REGVAL_ADAPTER_ENUM_SYNC570_PCI_2PORT, IDS_DisplayName_Sync570_PCI_2
         },
         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_SYNC570_PCI_4PORT, DIGI_PCI_SUBDEVICEID_SYNC570_PCI_4PORT,
            DXB_REGVAL_ADAPTER_ENUM_SYNC570_PCI_4PORT, IDS_DisplayName_Sync570_PCI_4
         },
         {
            DIGI_PCI_VENDORID, 0, 0,
            DXB_REGVAL_ADAPTER_ENUM_SYNC570_ISA_2PORT, IDS_DisplayName_Sync570_ISA_2
         },
         {
            DIGI_PCI_VENDORID, 0, 0,
            DXB_REGVAL_ADAPTER_ENUM_SYNC570_ISA_4PORT, IDS_DisplayName_Sync570_ISA_4
         },

         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_HOUSTON, DIGI_PCI_SUBDEVICEID_HOUSTON_T1_SINGLE,
            DXB_REGVAL_ADAPTER_ENUM_HOUSTON_T1_SINGLE, IDS_DisplayName_DigiHoustonT1Single
         },

         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_HOUSTON, DIGI_PCI_SUBDEVICEID_HOUSTON_T1_DUAL,
            DXB_REGVAL_ADAPTER_ENUM_HOUSTON_T1_DUAL, IDS_DisplayName_DigiHoustonT1Dual 
         },

         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_HOUSTON, DIGI_PCI_SUBDEVICEID_HOUSTON_E1_SINGLE,
            DXB_REGVAL_ADAPTER_ENUM_HOUSTON_E1_SINGLE, IDS_DisplayName_DigiHoustonE1Single
         },

         { 
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_HOUSTON, DIGI_PCI_SUBDEVICEID_HOUSTON_E1_DUAL,
            DXB_REGVAL_ADAPTER_ENUM_HOUSTON_E1_DUAL,   IDS_DisplayName_DigiHoustonE1Dual
         },

         {
            DIGI_PCI_VENDORID, DIGI_CPCI_DEVICEID_HOUSTON, DIGI_CPCI_SUBDEVICEID_HOUSTON_T1_SINGLE,
            DXB_REGVAL_ADAPTER_ENUM_HOUSTON_T1_SINGLE_CPCI, IDS_DisplayName_DigicPciHoustonT1Single
         },

         {
            DIGI_PCI_VENDORID, DIGI_CPCI_DEVICEID_HOUSTON, DIGI_CPCI_SUBDEVICEID_HOUSTON_T1_DUAL,
            DXB_REGVAL_ADAPTER_ENUM_HOUSTON_T1_DUAL_CPCI, IDS_DisplayName_DigicPciHoustonT1Dual 
         },

         {
            DIGI_PCI_VENDORID, DIGI_CPCI_DEVICEID_HOUSTON, DIGI_CPCI_SUBDEVICEID_HOUSTON_E1_SINGLE,
            DXB_REGVAL_ADAPTER_ENUM_HOUSTON_E1_SINGLE_CPCI, IDS_DisplayName_DigicPciHoustonE1Single
         },

         { 
            DIGI_PCI_VENDORID, DIGI_CPCI_DEVICEID_HOUSTON, DIGI_CPCI_SUBDEVICEID_HOUSTON_E1_DUAL,
            DXB_REGVAL_ADAPTER_ENUM_HOUSTON_E1_DUAL_CPCI,   IDS_DisplayName_DigicPciHoustonE1Dual
         },

         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_LONDON, DIGI_PCI_SUBDEVICEID_LONDON_ST,
            DXB_REGVAL_ADAPTER_ENUM_LONDON_ST, IDS_DisplayName_DigiLondonST
         },

         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_LONDON, DIGI_PCI_SUBDEVICEID_LONDON_U,
            DXB_REGVAL_ADAPTER_ENUM_LONDON_U,  IDS_DisplayName_DigiLondonU
         },

         // For W2K, we preserve the Chaska's DAA type in the identity,
         // for NT4, the PCI ID is interrogated at a later time
#if defined NT5
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_40, DXB_REGVAL_ADAPTER_ENUM_CHASKA_40, IDS_DisplayName_DigiChaska4 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_41, DXB_REGVAL_ADAPTER_ENUM_CHASKA_41, IDS_DisplayName_DigiChaska4 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_42, DXB_REGVAL_ADAPTER_ENUM_CHASKA_42, IDS_DisplayName_DigiChaska4 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_43, DXB_REGVAL_ADAPTER_ENUM_CHASKA_43, IDS_DisplayName_DigiChaska4 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_44, DXB_REGVAL_ADAPTER_ENUM_CHASKA_44, IDS_DisplayName_DigiChaska4 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_45, DXB_REGVAL_ADAPTER_ENUM_CHASKA_45, IDS_DisplayName_DigiChaska4 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_80, DXB_REGVAL_ADAPTER_ENUM_CHASKA_80, IDS_DisplayName_DigiChaska8 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_81, DXB_REGVAL_ADAPTER_ENUM_CHASKA_81, IDS_DisplayName_DigiChaska8 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_82, DXB_REGVAL_ADAPTER_ENUM_CHASKA_82, IDS_DisplayName_DigiChaska8 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_83, DXB_REGVAL_ADAPTER_ENUM_CHASKA_83, IDS_DisplayName_DigiChaska8 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_84, DXB_REGVAL_ADAPTER_ENUM_CHASKA_84, IDS_DisplayName_DigiChaska8 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_85, DXB_REGVAL_ADAPTER_ENUM_CHASKA_85, IDS_DisplayName_DigiChaska8 },
#else // #if defined NT5
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_40, DXB_REGVAL_ADAPTER_ENUM_CHASKA_4, IDS_DisplayName_DigiChaska4 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_41, DXB_REGVAL_ADAPTER_ENUM_CHASKA_4, IDS_DisplayName_DigiChaska4 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_42, DXB_REGVAL_ADAPTER_ENUM_CHASKA_4, IDS_DisplayName_DigiChaska4 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_43, DXB_REGVAL_ADAPTER_ENUM_CHASKA_4, IDS_DisplayName_DigiChaska4 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_44, DXB_REGVAL_ADAPTER_ENUM_CHASKA_4, IDS_DisplayName_DigiChaska4 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_45, DXB_REGVAL_ADAPTER_ENUM_CHASKA_4, IDS_DisplayName_DigiChaska4 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_80, DXB_REGVAL_ADAPTER_ENUM_CHASKA_8, IDS_DisplayName_DigiChaska8 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_81, DXB_REGVAL_ADAPTER_ENUM_CHASKA_8, IDS_DisplayName_DigiChaska8 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_82, DXB_REGVAL_ADAPTER_ENUM_CHASKA_8, IDS_DisplayName_DigiChaska8 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_83, DXB_REGVAL_ADAPTER_ENUM_CHASKA_8, IDS_DisplayName_DigiChaska8 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_84, DXB_REGVAL_ADAPTER_ENUM_CHASKA_8, IDS_DisplayName_DigiChaska8 },
         { DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_CHASKA, DIGI_PCI_SUBDEVICEID_CHASKA_85, DXB_REGVAL_ADAPTER_ENUM_CHASKA_8, IDS_DisplayName_DigiChaska8 },
#endif // #if defined NT5

         {
            IBM_PCI_VENDORID, IBM_PCI_DEVICEID_HOUSTON, IBM_PCI_SUBDEVICEID_HOUSTON_T1_SINGLE,
            DXB_REGVAL_ADAPTER_ENUM_HOUSTON_T1_SINGLE, IDS_DisplayName_DigiHoustonT1Single
         },

         {
            IBM_PCI_VENDORID, IBM_PCI_DEVICEID_HOUSTON, IBM_PCI_SUBDEVICEID_HOUSTON_T1_DUAL,
            DXB_REGVAL_ADAPTER_ENUM_HOUSTON_T1_DUAL, IDS_DisplayName_DigiHoustonT1Dual 
         },

         {
            IBM_PCI_VENDORID, IBM_PCI_DEVICEID_HOUSTON, IBM_PCI_SUBDEVICEID_HOUSTON_E1_SINGLE,
            DXB_REGVAL_ADAPTER_ENUM_HOUSTON_E1_SINGLE, IDS_DisplayName_DigiHoustonE1Single
         },

         { 
            IBM_PCI_VENDORID, IBM_PCI_DEVICEID_HOUSTON, IBM_PCI_SUBDEVICEID_HOUSTON_E1_DUAL,
            DXB_REGVAL_ADAPTER_ENUM_HOUSTON_E1_DUAL,   IDS_DisplayName_DigiHoustonE1Dual
         },

         {
            IBM_PCI_VENDORID, IBM_PCI_DEVICEID_LONDON, IBM_PCI_SUBDEVICEID_LONDON_ST,
            DXB_REGVAL_ADAPTER_ENUM_LONDON_ST, IDS_DisplayName_DigiLondonST
         },

         {
            IBM_PCI_VENDORID, IBM_PCI_DEVICEID_LONDON, IBM_PCI_SUBDEVICEID_LONDON_U,
            DXB_REGVAL_ADAPTER_ENUM_LONDON_U,  IDS_DisplayName_DigiLondonU
         },

         // For W2K, we preserve the Chaska's DAA type in the identity,
         // for NT4, the PCI ID is interrogated at a later time
#if defined NT5
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_40, DXB_REGVAL_ADAPTER_ENUM_CHASKA_40, IDS_DisplayName_DigiChaska4 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_41, DXB_REGVAL_ADAPTER_ENUM_CHASKA_41, IDS_DisplayName_DigiChaska4 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_42, DXB_REGVAL_ADAPTER_ENUM_CHASKA_42, IDS_DisplayName_DigiChaska4 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_43, DXB_REGVAL_ADAPTER_ENUM_CHASKA_43, IDS_DisplayName_DigiChaska4 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_44, DXB_REGVAL_ADAPTER_ENUM_CHASKA_44, IDS_DisplayName_DigiChaska4 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_45, DXB_REGVAL_ADAPTER_ENUM_CHASKA_45, IDS_DisplayName_DigiChaska4 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_80, DXB_REGVAL_ADAPTER_ENUM_CHASKA_80, IDS_DisplayName_DigiChaska8 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_81, DXB_REGVAL_ADAPTER_ENUM_CHASKA_81, IDS_DisplayName_DigiChaska8 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_82, DXB_REGVAL_ADAPTER_ENUM_CHASKA_82, IDS_DisplayName_DigiChaska8 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_83, DXB_REGVAL_ADAPTER_ENUM_CHASKA_83, IDS_DisplayName_DigiChaska8 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_84, DXB_REGVAL_ADAPTER_ENUM_CHASKA_84, IDS_DisplayName_DigiChaska8 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_85, DXB_REGVAL_ADAPTER_ENUM_CHASKA_85, IDS_DisplayName_DigiChaska8 },
#else // #if defined NT5
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_40, DXB_REGVAL_ADAPTER_ENUM_CHASKA_4, IDS_DisplayName_DigiChaska4 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_41, DXB_REGVAL_ADAPTER_ENUM_CHASKA_4, IDS_DisplayName_DigiChaska4 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_42, DXB_REGVAL_ADAPTER_ENUM_CHASKA_4, IDS_DisplayName_DigiChaska4 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_43, DXB_REGVAL_ADAPTER_ENUM_CHASKA_4, IDS_DisplayName_DigiChaska4 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_44, DXB_REGVAL_ADAPTER_ENUM_CHASKA_4, IDS_DisplayName_DigiChaska4 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_45, DXB_REGVAL_ADAPTER_ENUM_CHASKA_4, IDS_DisplayName_DigiChaska4 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_80, DXB_REGVAL_ADAPTER_ENUM_CHASKA_8, IDS_DisplayName_DigiChaska8 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_81, DXB_REGVAL_ADAPTER_ENUM_CHASKA_8, IDS_DisplayName_DigiChaska8 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_82, DXB_REGVAL_ADAPTER_ENUM_CHASKA_8, IDS_DisplayName_DigiChaska8 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_83, DXB_REGVAL_ADAPTER_ENUM_CHASKA_8, IDS_DisplayName_DigiChaska8 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_84, DXB_REGVAL_ADAPTER_ENUM_CHASKA_8, IDS_DisplayName_DigiChaska8 },
         { IBM_PCI_VENDORID, IBM_PCI_DEVICEID_CHASKA, IBM_PCI_SUBDEVICEID_CHASKA_85, DXB_REGVAL_ADAPTER_ENUM_CHASKA_8, IDS_DisplayName_DigiChaska8 },
#endif // #if defined NT5
         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_PRIME_T1_SINGLE, DIGI_PCI_SUBDEVICEID_PRIME_T1_SINGLE,
            DXB_REGVAL_ADAPTER_ENUM_PRIME_T1_PCI, IDS_DisplayName_PrimeT1
         },
         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_PRIME_E1_SINGLE, DIGI_PCI_SUBDEVICEID_PRIME_E1_SINGLE,
            DXB_REGVAL_ADAPTER_ENUM_PRIME_E1_PCI, IDS_DisplayName_PrimeE1
         },
         {
            0, 0, 0,
            DXB_REGVAL_ADAPTER_ENUM_PRIME_ISA, IDS_DisplayName_PrimeT1ISA
         },

         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_ACCELEPORT_2000, DIGI_PCI_SUBDEVICEID_ACCELEPORT_2R_2000,
            DXB_REGVAL_ADAPTER_ENUM_ACCELEPORT_2R_2000, IDS_DisplayName_AccelePort2r2000
         },
         
         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_ACCELEPORT_2000, DIGI_PCI_SUBDEVICEID_ACCELEPORT_4R_2000,
            DXB_REGVAL_ADAPTER_ENUM_ACCELEPORT_4R_2000, IDS_DisplayName_AccelePort4r2000
         },
         
         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_ACCELEPORT_2000, DIGI_PCI_SUBDEVICEID_ACCELEPORT_8R_2000,
            DXB_REGVAL_ADAPTER_ENUM_ACCELEPORT_8R_2000, IDS_DisplayName_AccelePort8r2000
         },
         
         {
            DIGI_PCI_VENDORID, DIGI_PCI_DEVICEID_ACCELEPORT_2000, DIGI_PCI_SUBDEVICEID_ACCELEPORT_16R_2000,
            DXB_REGVAL_ADAPTER_ENUM_ACCELEPORT_16R_2000, IDS_DisplayName_AccelePort16r2000
         },
      };

      TCHAR const * pszIdentity = TEXT("");
      int nDisplayNameID = 0;
      BOOL fAdapterFound = FALSE;

#ifndef NT5
      if (m_hwResources.IsPciBus())
      {
         for (int i = 0; i < ElementCount(aAdapterData); i++)
         {
             if ((m_hwResources.busSpecific.Pci.dwVendorID == aAdapterData[i].dwVendorID) &&
                (m_hwResources.busSpecific.Pci.dwPciID == aAdapterData[i].dwPciID) &&
                (m_hwResources.busSpecific.Pci.dwSubPciID == aAdapterData[i].dwSubPciID))
            {
               pszIdentity = aAdapterData[i].pszIdentity;
               nDisplayNameID = aAdapterData[i].nDisplayNameID;
               fAdapterFound = TRUE;
               break;
            }
         }
      }
      else if (m_hwResources.IsIsaOrEisaBus())
#endif
      {
         CString strIdentity = GetIdentity();
         AffirmThrow(!strIdentity.IsEmpty());

         for (int i = 0; i < ElementCount(aAdapterData); i++)
         {
            if (strIdentity.CompareNoCase(aAdapterData[i].pszIdentity)==0)
            {
               pszIdentity = aAdapterData[i].pszIdentity;
               nDisplayNameID = aAdapterData[i].nDisplayNameID;
               fAdapterFound = TRUE;
               break;
            }
         }
      }

	
      AffirmThrow(fAdapterFound);
      SetIdentity(pszIdentity);

      // Set our display name
      CString strDisplayName;
      AffirmThrow(strDisplayName.LoadString(nDisplayNameID));
      SetDisplayName(strDisplayName);

      // Set what we can do
      // In general, properties at the adapter level only involve ISA or EISA params...
      if (m_hwResources.IsIsaOrEisaBus())
         SetAbility(CConfigObject::DOPROPERTIES);
      else
         SetAbility(CConfigObject::NOABILITIES);

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

      // Init our bitmap
      AffirmThrow(m_WizBmp.Load(g_hInstance, IDB_DigiLogo, TRUE));

      // Give birth to our children
      for (int i = 0; i < m_cLines; i++)
      {
         AffirmThrow(AddChild(i));
      }
   }
   catch (CAffirmException ae)
   {
   }

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

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

   try
   {
#ifndef NT5
      AffirmThrow(m_hwResources.Get(m_hKey));
#endif

      // for NT5, the INF writes the identity string in the registry
      CString strident;
      AffirmThrow(RegReadStrValue(m_hKey, DXB_REGVAL_IDENTITY, strident));
      SetIdentity(strident);

      AffirmThrow(RegReadStrValue(m_hKey, DXB_REGVAL_OPTION, m_strOption));
      AffirmThrow(!m_strOption.IsEmpty());

      CString strVAdapterNum;
      AffirmThrow(RegReadStrValue(m_hKey, DXB_REGVAL_NDIS_ADAPTER_INSTANCE, strVAdapterNum, TEXT("0")));
      AffirmThrow(!strVAdapterNum.IsEmpty());
      m_nVAdapterNum = atoi(strVAdapterNum);

      AffirmThrow(RegReadStrValue(m_hKey, DXB_REGVAL_BIOS, m_strBiosImagePath));
      // NOTE:
      //    Some adapters DON'T have a BIOS image!
      // AffirmThrow(!m_strBiosImagePath.IsEmpty());

      AffirmThrow(RegReadStrValue(m_hKey, DXB_REGVAL_FEP, m_strFepImagePath));
      // NOTE:
      //    Some adapters DON'T have a FEP image!
      // AffirmThrow(!m_strFepImagePath.IsEmpty());

      AffirmThrow(RegReadIntValue(m_hKey, DXB_REGVAL_NUMBEROFLINES, &m_cLines, DXB_REGVAL_NUMBEROFLINES_DEFAULT));
      AffirmThrow(m_cLines > 0);

      AffirmThrow(RegReadStrValue(m_hKey, DXB_REGVAL_SERVICENAME, m_strServiceName));
      AffirmThrow(!m_strServiceName.IsEmpty());

      // If the Device Name is not in the Config Data then use the Service Name
      if (m_strDeviceName.IsEmpty())
      {
         m_strDeviceName = m_strServiceName;
      }

#if defined NT5
      AffirmThrow(RegReadIntValue(m_hKey, DXB_REGVAL_HAS_WIZARD, &m_nHasWizard, DXB_REGVAL_HAS_WIZARD_DEFAULT));
#endif // #if defined NT5

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

   return fSuccess;
}

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

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

#ifndef NT5
      AffirmThrow(m_hwResources.Set(m_hKey));
#endif

      AffirmThrow(RegWriteStrValue(m_hKey, DXB_REGVAL_BIOS, m_strBiosImagePath));
      AffirmThrow(RegWriteStrValue(m_hKey, DXB_REGVAL_FEP, m_strFepImagePath));

      AffirmThrow(RegWriteIntValue(m_hKey, DXB_REGVAL_NUMBEROFLINES, m_cLines));

#ifdef NT5
      // restart DXB
      CString strInstance;
      AffirmThrow(RegReadStrValue(m_hKey, DXB_REGVAL_REGINSTANCE, strInstance));

      // Now that we've written our parameters, we don't need to spoof anymore...
      // Note that the driver will turn this off too the first time it gets loaded
      AffirmThrow(RegWriteIntValue(m_hKey,DXB_REGVAL_SPOOF,DXB_REGVAL_SPOOF_OFF));

      // For now restart done in TreeDialog::OnOK. Once we figure out why
      // a synthesized HDevInfo is not working, we can turn on this code
      // and turn it off in TreeDialog
      //    RestartService(strInstance);
#endif

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

   return fSuccess;
}

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

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

   try
   {
      CString strConfigDataRegPath;
      AffirmThrow(BuildConfigDataRegPath(strConfigDataRegPath));

      HKEY hConfigData = NULL;
      AffirmThrow(RegOpenKey(HKEY_LOCAL_MACHINE, strConfigDataRegPath, &hConfigData));
      AffirmThrow(hConfigData != NULL);

      try
      {
         AffirmThrow(RegReadIntValue(hConfigData, DXB_REGVAL_MAX_PORTS, &m_cMaxPorts));
         AffirmThrow(RegReadBoolValue(hConfigData, DXB_REGVAL_ASKMULTILINES, &m_fAskMultiLines, TRUE));
         AffirmThrow(RegReadStrValue(hConfigData, DXB_REGVAL_DEVICE, m_strDeviceName));

          // If the Device Name is not in the Config Data then use the Service Name
         if (m_strDeviceName.IsEmpty())
         {
            m_strDeviceName = m_strServiceName;
         }

         // Need this for S/Dxb logical channel index
         AffirmThrow(RegReadIntValue(hConfigData, DXB_REGVAL_MAX_LOGICAL_CHANS_PER_LINE, &m_cMaxLogicalChannelsPerLine));
         TRACE("CAdapter::GetConfigData(): m_cMaxLogicalChannelsPerLine:%d\n", m_cMaxLogicalChannelsPerLine);
#if defined NT5
         (void)RegReadIntValue(hConfigData, DXB_REGVAL_ASYN_MODEMDEVICE, &m_nHasModems);
#else // #if defined NT5
	 
		 // only for the ISA bus do we need to read the possible choices for Io, mem & irq settings
         AffirmThrow(m_hwResources.eBusType != SHWResources::InterfaceTypeUndefined);
         if (m_hwResources.IsIsaOrEisaBus())
         {
            AffirmThrow(RegReadMultiStrValue(hConfigData, DXB_REGVAL_IO_CHOICES, m_astrIoChoices));
            AffirmThrow(RegReadMultiStrValue(hConfigData, DXB_REGVAL_MEM_CHOICES, m_astrMemChoices));
            AffirmThrow(RegReadMultiStrValue(hConfigData, DXB_REGVAL_IRQ_CHOICES, m_astrIrqChoices));
         }

		 AffirmThrow(RegReadIntValue(hConfigData, DXB_REGVAL_HAS_WIZARD, &m_nHasWizard, DXB_REGVAL_HAS_WIZARD_DEFAULT));

#endif // #if defined NT5
      }
      catch (CAffirmException ae)
      {
      }

      RegCloseKey(hConfigData);

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

   return fSuccess;
}

BOOL CAdapter::AddChild(void)
{
   BOOL fSuccess = FALSE;

   try
   {
      for (int i = 0; i < m_cLines; i++)
      {
         BOOL fChildAlreadyExists = FALSE;

         for (int j = 0; j < m_apChildren.GetSize(); j++)
         {
            AffirmThrow(m_apChildren[j] != NULL);
            CLine * pChild = (CLine *)m_apChildren[j];

            if (i == pChild->GetLineNumber())
            {
               fChildAlreadyExists = TRUE;
               break;
            }
         }

         if (!fChildAlreadyExists)
         {
            AffirmThrow(AddChild(i));
            fSuccess = TRUE;
            break;
         }
      }
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

BOOL CAdapter::AddChild(int const nChild)
{
   BOOL fSuccess = FALSE;

   try
   {
      AffirmThrow(nChild >= 0);

      INT_PTR iNewChild = m_apChildren.Add(NULL);

      // This registry path thingie needs a little explanation!
      //    Here's the layout so far:
      //       ...\DigiDxb?\Parameters          (where ? = the adapter instance)
      //    The line parameters reside at:
      //       ...\DigiDxb?\Parameters\N        (where N = 0, 1, ... # of lines)
      //    So, pass in the current hKey, and the path to the line key

      CString strLine;
      strLine.Format("%d", nChild);
      AffirmThrow(NewConfigObject(&m_apChildren[iNewChild], CConfigObject::LINE, TEXT("Line") + m_strOption, m_hKey, strLine, this));
      AffirmThrow(m_apChildren[iNewChild] != NULL);

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

   return fSuccess;
}

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

CString CAdapter::GetInformationText(void)
{
   CString strInfo;
   if (m_hwResources.IsIsaOrEisaBus())
   {
       CString strFmt((LPCTSTR)IDS_ISA_FMT);
       strInfo.Format(strFmt, GetDisplayName(), m_hwResources.busSpecific.Isa.dwIOBaseAddress,
          m_hwResources.busSpecific.Isa.dwMemoryMappedBaseAddress,
          m_hwResources.busSpecific.Isa.dwInterruptNumber);
   
   }
   else
       strInfo = GetDisplayName();
   return strInfo;
}

BOOL CAdapter::DoProperties(void)
{
   BOOL fSuccess = FALSE;

   try
   {
      if (m_hwResources.IsIsaOrEisaBus())
      {
         // for Isa bus, bring up a dialog that allows user to change
         // hardware resources
         CPropertySheet sheet;
         CISAResources resourcepage;

         resourcepage.SetChoices(m_astrIoChoices, m_hwResources.busSpecific.Isa.dwIOBaseAddress,
            m_astrMemChoices, m_hwResources.busSpecific.Isa.dwMemoryMappedBaseAddress,
            m_astrIrqChoices, m_hwResources.busSpecific.Isa.dwInterruptNumber);

         sheet.AddPage(&resourcepage);
         if (sheet.DoModal() == IDOK)
         {
            AffirmThrow(resourcepage.GetChoices(m_hwResources.busSpecific.Isa.dwIOBaseAddress,
               m_hwResources.busSpecific.Isa.dwMemoryMappedBaseAddress,
               m_hwResources.busSpecific.Isa.dwInterruptNumber));
            fSuccess = TRUE;
         }
      }
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

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

BOOL CAdapter::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

      m_pwsSheet = pSheet;

      m_pwsSheet->SetTitleBase(GetDisplayName() + TEXT(" - "));

      CPoint ptBmpPlacement(0);
      m_pwsSheet->SetDefaultPageBitmap(&m_WizBmp, ptBmpPlacement);

      if (m_pwpWelcome == NULL) m_pwpWelcome = new CWizPageGenericWelcome(this, WP_WELCOME, GetDisplayName());
      AffirmThrow(m_pwpWelcome != NULL);
      AffirmThrow(m_pwsSheet->InsertPage(m_pwpWelcome, FALSE, TRUE));      // 1st page is always permanent

      if (m_pwpDone == NULL) m_pwpDone = new CWizPageGenericDone(this, WP_DONE);
      AffirmThrow(m_pwpDone != NULL);
      AffirmThrow(m_pwsSheet->InsertPage(m_pwpDone, FALSE, TRUE));         // Last page is too

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

   return fSuccess;
}

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

   try
   {
      AffirmThrow(pSheet != NULL);

      if (m_pwsSheet != NULL)
      {
         AffirmThrow(m_pwsSheet == pSheet);

         if (m_pwpWelcome != NULL)        m_pwsSheet->RemovePage(m_pwpWelcome);
         if (m_pwpMultiLines != NULL)     m_pwsSheet->RemovePage(m_pwpMultiLines);
         if (m_pwpDone != NULL)           m_pwsSheet->RemovePage(m_pwpDone);
         if (m_pwpIsaResources != NULL)   m_pwsSheet->RemovePage(m_pwpIsaResources);
      }

      AffirmThrow(CAdapter::RemoveWizardPages(pSheet));

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

   return fSuccess;
}

BOOL CAdapter::AddLineWizardPages(int const cLinesToAdd)
{
   BOOL fSuccess = FALSE;

   try
   {
      AffirmThrow(m_pwsSheet != NULL);
      AffirmThrow(cLinesToAdd > 0);

      // Remove any pages the lines may have added
      for (int i = 0; i < m_cLines; i++)
      {
         AffirmThrow(m_apChildren[i] != NULL);
         AffirmThrow(m_apChildren[i]->RemoveWizardPages(m_pwsSheet));
      }

      // Add line pages
      for (i = 0; i < cLinesToAdd; i++)
      {
         AffirmThrow(m_apChildren[i] != NULL);
         AffirmThrow(m_apChildren[i]->AddWizardPages(m_pwsSheet));
      }

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

   return fSuccess;
}

BOOL CAdapter::AddMultiLinePage(void)
{
   BOOL fSuccess = FALSE;
   try
   {
      AffirmThrow(m_pwsSheet != NULL);
      if ((m_cLines > 1) && (m_fAskMultiLines))
      {
         if (m_pwpMultiLines == NULL) m_pwpMultiLines = new CWizPageMultipleLines(this, WP_MULTILINES);
         AffirmThrow(m_pwpMultiLines != NULL);

         if (!m_pwsSheet->InsertPage(m_pwpMultiLines, FALSE, TRUE)) // This page needs to be permanent
            TRACE("InsertPage failed!  Multi lines page must already be in list.\n");
      }
      else
      {
         AffirmThrow(AddLineWizardPages(m_cLines));
      }
      fSuccess = TRUE;
   }
   catch(CAffirmException ae)
   {
   }
   return fSuccess;
}

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

   try
   {
      AffirmThrow(m_pwsSheet != NULL);
      if (m_hwResources.IsIsaOrEisaBus())
      {
         if (m_pwpIsaResources == NULL) m_pwpIsaResources = new CISAResources(this, WP_RESOURCES);
         AffirmThrow(m_pwpIsaResources != NULL);

         m_pwpIsaResources->SetChoices(m_astrIoChoices, m_hwResources.busSpecific.Isa.dwIOBaseAddress,
         m_astrMemChoices, m_hwResources.busSpecific.Isa.dwMemoryMappedBaseAddress,
         m_astrIrqChoices, m_hwResources.busSpecific.Isa.dwInterruptNumber);

         AffirmThrow(m_pwsSheet->InsertPage(m_pwpIsaResources));
      }
      else
      {
         AffirmThrow(AddMultiLinePage());
      }

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

   return fSuccess;
}

BOOL CAdapter::HandleWizMultiLines(void)
{
   BOOL fSuccess = FALSE;

   try
   {
      AffirmThrow(m_pwsSheet != NULL);
      AffirmThrow(m_cLines > 1);
      AffirmThrow(m_fAskMultiLines);
      AffirmThrow(m_pwpMultiLines != NULL);

      int cLinePagesToAdd = (m_pwpMultiLines->AllLinesTheSame()) ? 1 : m_cLines;
      AffirmThrow(AddLineWizardPages(cLinePagesToAdd));

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

   return fSuccess;
}

BOOL CAdapter::HandleWizDone(void)
{
   BOOL fSuccess = FALSE;

   try
   {
      AffirmThrow(m_pwsSheet != NULL);

      if ((m_cLines > 1) && m_fAskMultiLines)
      {
         AffirmThrow(m_pwpMultiLines != NULL);
         if (m_pwpMultiLines->AllLinesTheSame())
         {
            // Copy line parameters
            for (int i = 1; i < m_cLines; i++)
               AffirmThrow(m_apChildren[i]->CopyParameters(m_apChildren[0]));
         }
      }

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

   return fSuccess;
}

BOOL CAdapter::HandleResources(void)
{
   BOOL fSuccess = FALSE;
   try
   {
      AffirmThrow(m_pwpIsaResources->GetChoices(m_hwResources.busSpecific.Isa.dwIOBaseAddress,
      m_hwResources.busSpecific.Isa.dwMemoryMappedBaseAddress,
      m_hwResources.busSpecific.Isa.dwInterruptNumber));
      AffirmThrow(AddMultiLinePage());
      fSuccess = TRUE;
   }
   catch(CAffirmException ae)
   {
   }
   return fSuccess;
}

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

   try
   {
      switch (nState)
      {
         case WP_WELCOME:     AffirmThrow(HandleWizWelcome());    break;
         case WP_RESOURCES:   AffirmThrow(HandleResources());     break;
         case WP_MULTILINES:  AffirmThrow(HandleWizMultiLines()); break;
         case WP_DONE:        AffirmThrow(HandleWizDone());       break;
         default: AffirmThrow(FALSE); break;
      }

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

   return fSuccess;
}


