/*****************************************************************************
* 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
*
*****************************************************************************/

// ProtocolSna.cpp: implementation of the CProtocolSna class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ProtocolSna.h"
#include "ObjectFactory.h"
#include "SnaConfig.h"
#include "RegHelpers.h"
#include "Adapter.h"


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

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

IMPLEMENT_DYNAMIC(CProtocolSna, CProtocol)

// declare our statics
BOOL CProtocolSna::m_bMSServerInstalled = FALSE;	// flag for MS SNA server
BOOL CProtocolSna::m_bIBMServerInstalled = FALSE;   // flag for IBM SNA server

CProtocolSna::CProtocolSna(HKEY const hKeyRoot, CString const strRegPath, CConfigObject const * const pParent) : CProtocol(hKeyRoot, strRegPath, pParent)
{
 //  try
 //  {

		// solve the identity crisis
	   SetIdentity(DXB_REGVAL_PROTOCOL_ENUM_SNA);

	   // get our static config data
	   AffirmThrow(CProtocol::GetConfigData());
       
	   CAdapter* pAdapter = (CAdapter*)(pParent->GetParent());
	   ASSERT_KINDOF(CAdapter,pAdapter);

		INT_PTR TotalConfiguredPorts = pAdapter->GetConfiguredPorts();
		// now clamp against available ports on the adapter
		if ((m_cMaxPorts +  TotalConfiguredPorts) > pAdapter->GetAdapterMaxPorts())
   {
			CString strMsgFmt((LPCTSTR)IDS_VCADAPTERLIMIT);
			CString strErrMsg;
			strErrMsg.Format(strMsgFmt,pAdapter->GetAdapterMaxPorts());
			AfxMessageBox(strErrMsg);

			AffirmThrow(FALSE);
		}

	   // Get adapter parameters
	   AffirmThrow(GetParameters());

	   // Set our Display Name
	   CString szDisplayName;
	   AffirmThrow(szDisplayName.LoadString(IDS_DisplayName_Protocol));
	   SetDisplayName(szDisplayName);

	   // define our abilities
	   // we don't allow adding/deleting childs from the GUI. Defining the
	   // SNA protocol automatically creates the service which is simply 
	   // a holder object allowing us to create
	   SetAbility(CConfigObject::DOPROPERTIES);
	

       m_astrServices.Copy(m_astrServicesAllowed);
      // Give birth to our children

       for (int i = 0; i < m_astrServices.GetSize(); i++)
       {
		   m_apChildren.SetAtGrow(i, NULL);

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

         CString strServiceRegPath = m_astrServices[i] + TEXT("\\") + strRegPath;
		 TRACE("DIGISNA.DLL,CProtocolSna: NewObjReg(%s)\n", (LPCTSTR)strServiceRegPath);
         AffirmThrow(NewConfigObject(&m_apChildren[i], CConfigObject::SERVICE, m_astrServices[i], hKeyRoot, strServiceRegPath, this));
         AffirmThrow(m_apChildren[i] != NULL);
      }

//   }
//   catch (CAffirmException ae)
//   {
	   
//  }

}

CProtocolSna::~CProtocolSna()
{
   try
   {
   }
   catch (CAffirmException ae)
   {
   }

}

BOOL CProtocolSna::SetParameters()
{
	BOOL bSuccess = FALSE;
	try
	{
		AffirmThrow(CProtocol::SetParameters());
		// make sure that all SNA server related DLL's have been copied over 
		if (m_bMSServerInstalled)
			AffirmThrow(CopyMSSNAFiles());
		if (m_bIBMServerInstalled)
		{
			AffirmThrow(ModifyIBMSNARegistry());
		}
		bSuccess = TRUE;
	}
	catch(CAffirmException ae)
	{
	}
	return bSuccess;
}


BOOL CProtocolSna::GetParameters()
{
	BOOL bSuccess = FALSE;
	try
	{
		AffirmThrow(CProtocol::GetParameters());
		bSuccess = TRUE;
	}
	catch(CAffirmException ae)
	{
	}
	return bSuccess;

}

BOOL CProtocolSna::RemoveParameters(BOOL fRemoveKey)
{
   BOOL fSuccess = FALSE;

   try
   {
      AffirmThrow(CProtocol::RemoveParameters(fRemoveKey));
      fSuccess = TRUE;
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

// really no protocol config for SNA. SNA server will instruct on how to 
// format the line
BOOL CProtocolSna::AddWizardPages(CConfigWizSheet * const pSheet)
{
	return TRUE;
}

// see comments for AddWizardPages
BOOL CProtocolSna::NextWizardPage(int const State)
{
	return TRUE;
}

// we should simply pop up a dialog box informing that SNA server will do
// all the configuration 
BOOL CProtocolSna::DoProperties(void)
{
	CSnaConfig dlg;
	dlg.DoModal();
	
	// Since our dialog is merely infomational, do nothing
	return FALSE;
}

// copy SNA dll's across as well as modify SNA reg parameters
/*
The DLL's DIGSDCFG.DLL and DIGXCFG.DLL need to be copied in the SNA\System\hwsetup\i386 directory (there is a similar alpha dir as well)
The Driver DIGISNA.SYS needs to be copied in the SNA\System directory

To find out where SNA is installed 
key : HKLM\Software\Microsoft\Sna Server\CurrentVersion\Setup
value: RootDir

Some registry modifications need to be made as well
key: HKLM\System\CurrentControlSet\Services\SnaBase\LinkServicesInstalled

add the following two REG_SZ values
value name: "Digi SDLC Link Service"     
value data: "DIGSDCFG.DLL"

value name: "Digi X.25 Link Service"
value data: "DIGXCFG.DLL"
*/

#define SNASOFTWAREKEY	_T("Software\\Microsoft\\Sna Server\\CurrentVersion\\Setup")
#define SNALSIKEY _T("System\\CurrentControlSet\\Services\\SnaBase\\LinkServicesInstalled")
#define SNADIGIDRIVER _T("DIGISNA.SYS")
#define SNADIGISDLCDLL   _T("DIGSDCFG.DLL")
#define SNADIGISDLCDESC  _T("Digi SDLC Link Service")
#define SNADIGIX25DLL    _T("DIGXCFG.DLL")
#define SNADIGIX25DESC    _T("Digi X.25 Link Service")
#define SNAROOTDIRKEY	_T("RootDir")
#define SNASYSTEMDIR	_T("\\System")
#define SNASYSTEM32DIR	_T("\\System32")
#define SNAHWSETUPDIR   _T("\\hwsetup")

#ifdef _M_ALPHA
#define SNACPUDIR   _T("\\Alpha")
#else
#define SNACPUDIR	_T("\\i386")
#endif

#define SNAINVALIDROOT  _T("xxx")

BOOL CProtocolSna::CopyMSSNAFiles()
{
	BOOL bSuccess = FALSE;
	HKEY hkey;
	try
	{
		AffirmThrow(RegOpenKeyEx(HKEY_LOCAL_MACHINE,SNASOFTWAREKEY,0,KEY_ALL_ACCESS,&hkey) == ERROR_SUCCESS);

		// get location where SNA is installed. Not doing much for path validity. Relying
		// on the fact that SNA will install properly and no one will muck with the
		// RootDir value
		CString szSNARootPath;
		RegReadStrValue(hkey,SNAROOTDIRKEY,szSNARootPath,SNAINVALIDROOT);
		RegCloseKey(hkey);
		AffirmThrow(szSNARootPath.CompareNoCase(SNAINVALIDROOT) != 0);
		
		// get windows drivers directory 
		TCHAR buffer[MAX_PATH];
		AffirmThrow(GetSystemDirectory(buffer,sizeof(buffer)));
		CString szSystem32(buffer);
		CString szSystem32_Drivers = szSystem32;
      szSystem32_Drivers += _T("\\Drivers");

		// start copying files
		szSNARootPath += SNASYSTEMDIR;
#if defined NT5
		AffirmThrow(CopyFile(szSystem32_Drivers,szSNARootPath,SNADIGIDRIVER));
#else // #if defined NT5
		AffirmThrow(CopyFile(szSystem32,szSNARootPath,SNADIGIDRIVER));
#endif // #if defined NT5

		// verify that the HWSETUP\I386 directory is installed
		// if user installs SNA without installing LinkServices
		// this directory will not be created. We need to create it
		// The path needs to be created 1 directory at a time
		szSNARootPath += SNAHWSETUPDIR;
		if (!CreateDirectory(szSNARootPath,NULL))
		{
			AffirmThrow(GetLastError() == ERROR_ALREADY_EXISTS);	
		}
		szSNARootPath += SNACPUDIR;
		if (!CreateDirectory(szSNARootPath,NULL))
		{
			AffirmThrow(GetLastError() == ERROR_ALREADY_EXISTS);	
		}

		AffirmThrow(CopyFile(szSystem32,szSNARootPath,SNADIGISDLCDLL));
		AffirmThrow(CopyFile(szSystem32,szSNARootPath,SNADIGIX25DLL));
		
		// Inform SNA of our added DLL's.
		// create the LinkServicesInstalled key, if it doesn't already exist
		// since its possible that the user never installed LinkServices
		AffirmThrow(RegCreateKey(HKEY_LOCAL_MACHINE,SNALSIKEY,&hkey));
		AffirmThrow(RegWriteStrValue(hkey,SNADIGISDLCDESC,SNADIGISDLCDLL));
		AffirmThrow(RegWriteStrValue(hkey,SNADIGIX25DESC,SNADIGIX25DLL));
		RegCloseKey(hkey);

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

	return bSuccess;
}

// copy a file lpszfile from source location to destination location
BOOL CProtocolSna::CopyFile(LPCTSTR lpszsrc,LPCTSTR lpszdest,LPCTSTR lpszfile)
{
	ASSERT(lpszsrc && lpszdest && lpszfile);
	BOOL bSuccess = TRUE;
	CString szSrc(lpszsrc);
	CString szDest(lpszdest);
	szSrc += _T("\\");
	szSrc += lpszfile;
	szDest += _T("\\");
	szDest += lpszfile;

	// always overwrite the existing file
	if (!::CopyFile(szSrc,szDest,FALSE))
	{
		DWORD err = GetLastError();

		LPVOID lpMsgBuf;
		FormatMessage( 
			FORMAT_MESSAGE_ALLOCATE_BUFFER | 
			FORMAT_MESSAGE_FROM_SYSTEM | 
			FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			err,
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
			(LPTSTR) &lpMsgBuf,
			0,
			NULL 
			);
		AfxMessageBox((LPCTSTR)lpMsgBuf,MB_OK | MB_ICONINFORMATION);
		// Free the buffer.
		LocalFree( lpMsgBuf );
		bSuccess = FALSE;
	}

	return bSuccess;
	
}

// following are related IBM CommServer package
#define IBMSNASOFTWAREKEY	_T("Software\\IBM\\OEM_CONFIG")
#define IBMSNADIGIDRIVER	_T("DIGISNA.SYS")
#define IBMSNADIGIDLCDLL	_T("\\DIGICSNT.DLL")

// SDLC config
#define IBMSNADIGISDLCKEY	_T("DIGI\\SDLCDLC")
#define IBMSNADIGISDLCDESC  _T("Digi SDLC")
#define IBMSNADIGISDLCNAME	_T("DigiSDLC")

// X25 config
#define IBMSNADIGIX25KEY	_T("DIGI\\X25DLC")
#define IBMSNADIGIX25DESC	_T("Digi X25")
#define IBMSNADIGIX25NAME	_T("DigiX25")

#define IBMSNASERVICEKEY    _T("System\\CurrentControlSet\\Services\\DigiSna")
BOOL CProtocolSna::ModifyIBMSNARegistry()
{
	BOOL bSuccess = FALSE;
	try
	{
		HKEY hRootkey;
		AffirmThrow(RegOpenKeyEx(HKEY_LOCAL_MACHINE,IBMSNASOFTWAREKEY,0,KEY_ALL_ACCESS,&hRootkey) == ERROR_SUCCESS);
		
		// Inform IBM SNA of ourselves 
		HKEY hkey;
		AffirmThrow(RegCreateKey(hRootkey,IBMSNADIGISDLCKEY,&hkey));
		AffirmThrow(RegWriteStrValue(hkey,_T("CFG_DLC_DESC"),IBMSNADIGISDLCDESC));
		AffirmThrow(RegWriteStrValue(hkey,_T("CFG_DLC_NAME"),IBMSNADIGISDLCNAME));
		AffirmThrow(RegWriteStrValue(hkey,_T("CFG_DLC_TYPE"),_T("SDLC_DLC_IBM")));

		TCHAR buffer[MAX_PATH];
		AffirmThrow(GetSystemDirectory(buffer,sizeof(buffer)));
		CString szDllPath(buffer);
		szDllPath += IBMSNADIGIDLCDLL;
		AffirmThrow(RegWriteStrValue(hkey,_T("CFG_DLL_PATH"),szDllPath));


		RegCloseKey(hkey);

		AffirmThrow(RegCreateKey(hRootkey,IBMSNADIGIX25KEY,&hkey));
		AffirmThrow(RegWriteStrValue(hkey,_T("CFG_DLC_DESC"),IBMSNADIGIX25DESC));
		AffirmThrow(RegWriteStrValue(hkey,_T("CFG_DLC_NAME"),IBMSNADIGIX25NAME));
		AffirmThrow(RegWriteStrValue(hkey,_T("CFG_DLC_TYPE"),_T("X25_DLC_IBM")));
		AffirmThrow(RegWriteStrValue(hkey,_T("CFG_DLL_PATH"),szDllPath));


		AffirmThrow(RegWriteStrValue(hkey,_T("CFG_DLL_PATH"),szDllPath));


		RegCloseKey(hkey);


		RegCloseKey(hRootkey);

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

	return bSuccess;
}


BOOL CProtocolSna::IsSnaInstalled()
{
	m_bMSServerInstalled = RegKeyExists(HKEY_LOCAL_MACHINE,SNASOFTWAREKEY);
	m_bIBMServerInstalled = RegKeyExists(HKEY_LOCAL_MACHINE,IBMSNASOFTWAREKEY);

	return ((m_bIBMServerInstalled || m_bMSServerInstalled)?TRUE:FALSE);
}