text: // @@@ START COPYRIGHT @@@
  //
  // Licensed to the Apache Software Foundation (ASF) under one
  // or more contributor license agreements.  See the NOTICE file
  // distributed with this work for additional information
  // regarding copyright ownership.  The ASF licenses this file
  // to you under the Apache License, Version 2.0 (the
  // "License"); you may not use this file except in compliance
  // with the License.  You may obtain a copy of the License at
  //
  //   http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing,
  // software distributed under the License is distributed on an
  // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  // KIND, either express or implied.  See the License for the
  // specific language governing permissions and limitations
  // under the License.
  //
  // @@@ END COPYRIGHT @@@
  //
  //
  #include "CDataSource.h"
  #include "NLSFunctions.h"
  #include "Transport.h"
  
  // Implements the member functions of CDataSource
  
  #define MAX_REGKEY_PATH_LEN			512
  #define	ODBC_DS_KEY					"SOFTWARE\\ODBC\\ODBC.INI\\"
  #define ODBC_CERTIFICATE_KEY		"SOFTWARE\\ODBC\\ODBCINST.INI\\TRAF ODBC 2.3"
  #define SYSTEM_DEFAULT				"SYSTEM_DEFAULT"
  #define NO_TIMEOUT					"NO_TIMEOUT"
  #define CONNECTION_TIMEOUT_DEFAULT	60
  #define LOGIN_TIMEOUT_DEFAULT		60
  #define	QUERY_TIMEOUT_DEFAULT		0
  #define IOCOMPRESSION_DEFAULT       1000
  #define FETCH_BUFFER_SIZE_DEFAULT	512 * 1024
  //#define FETCH_BUFFER_SIZE_DEFAULT   0
  
  
  CDataSource::CDataSource()
  {
  	m_DSName[0] = '\0';
  	m_DSLocation = 0;
  	m_DSServer[0] = '\0';
  	m_DSCatalog[0] = '\0';
  	m_DSCtrlInferNCHAR = FALSE;
  	m_DSCharSet = 0;
  	m_DSDataLang = MAKELCID (MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), SORT_DEFAULT);
  	m_DSErrorMsgLang = MAKELCID (MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), SORT_DEFAULT);
  	m_DSFetchBufferSize = FETCH_BUFFER_SIZE_DEFAULT;
  	m_DSSchema[0] = '\0';
  	m_DSConnectionTimeout = CONNECTION_TIMEOUT_DEFAULT;
  	m_DSLoginTimeout = LOGIN_TIMEOUT_DEFAULT;
  	m_DSQueryTimeout = QUERY_TIMEOUT_DEFAULT;
  	m_DSTranslationDLL[0] = '\0';
  	m_DSTranslationOption = 0;
  	m_DSReplacementChar[0] = '\0';
  	m_DSSelectRowsets = TRUE;
  	m_DSRowsetErrorRecovery = FALSE;
  	m_DSServerDSName[0] = 0;
  	m_DSServiceName[0] = 0;
  	m_DSSession[0] = '\0';
  	m_DSApplication[0] = '\0';
  	m_DSRoleName[0] = '\0';
  	m_DSCertificateDir[0] = '\0';
  	m_DSCertificateFile[0] = '\0';
  	m_DSCertificateFileActive[0] = '\0';
  	m_DSIOCompression = 0;
  
  	DWORD	error;
  	HKEY	keyHandle;
  	DWORD	keyValueLength;
  	DWORD	keyValueType;
  	error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  						 ODBC_CERTIFICATE_KEY,
  						 0,
  						 KEY_READ,
  						 &keyHandle);
  	if (error == ERROR_SUCCESS)
  	{
  		// Read CertificateDir	Value
  		keyValueLength = sizeof(m_DSCertificateDir);
  		error = RegQueryValueEx (keyHandle,
  						   "CertificateDir",
  						   NULL,				// Reserved
  						   &keyValueType,
  						   (LPBYTE)m_DSCertificateDir,
  						   &keyValueLength);
  		if (error != ERROR_SUCCESS)
  			m_DSCertificateDir[0] = '\0';
  		RegCloseKey(keyHandle);
  	}
  	else 
  		m_DSCertificateDir[0] = '\0';
  }
  
  short CDataSource::readDSValues(char *DSName, char* transError)
  {
  
  	DWORD	error;
  	char	searchKey[MAX_REGKEY_PATH_LEN+1];
  	HKEY	keyHandle;
  	BYTE	keyValueBuf[256];
  	DWORD	keyValueLength;
  	DWORD	keyValueType;
  	long	tempValue;
  	short	i = 0;
  	SQLRETURN retcode = ERROR_SUCCESS;
  	int translen;
  	wchar_t	tmpWBuf[MAX_SQL_IDENTIFIER_LEN + 1];
  
  	strcpyUTF8(m_DSName, (const char *)DSName, sizeof(m_DSName));
  
  	for (i = 0; i < 2 ; i++)
  	{
  		strcpy(searchKey, ODBC_DS_KEY);
  		if ( i == 0)
  			strcat(searchKey, (const char *)DSName);
  		else
  			strcat(searchKey, "DEFAULT");
  
  		error = RegOpenKeyEx(HKEY_CURRENT_USER
  						   ,searchKey
  						   ,0
  						   ,KEY_READ
  						   ,&keyHandle);
  		if (error == ERROR_SUCCESS)
  		{
  			m_DSLocation = HKCU_DSN; // HKCU
  			// Read AssociationService	Value
  			tmpWBuf[0] = L'\0';
  			keyValueLength = sizeof(tmpWBuf);
  			error = RegQueryValueExW (keyHandle,
  							   L"Server",
  							   NULL,				// Reserved
  							   &keyValueType,
  							   (LPBYTE)tmpWBuf,
  							   &keyValueLength);
  			if (error != ERROR_SUCCESS)
  			{
  				error = RegQueryValueExW (keyHandle,
  							   L"AssociationService",
  							   NULL,				// Reserved
  							   &keyValueType,
  							   (LPBYTE)tmpWBuf,
  							   &keyValueLength);
  				if (error != ERROR_SUCCESS)
  				{
  					RegCloseKey( keyHandle);
  					if (retcode == ERROR_SUCCESS)
  						retcode = DS_AS_KEY_NOT_FOUND;
  				}
  				else
  				{
  					retcode = ERROR_SUCCESS;
  				}
  			}
  			else
  			{
  				retcode = ERROR_SUCCESS;
  			}
  			if (error == ERROR_SUCCESS)
  			{
  				// translate m_DSServer to UTF8
  				transError[0] = '\0';
  				if(wcslen((wchar_t*)tmpWBuf) > 0)
  				{
  					if (WCharToUTF8((wchar_t*) tmpWBuf, wcslen((wchar_t*)tmpWBuf), m_DSServer, sizeof(m_DSServer), &translen, transError)!= SQL_SUCCESS)
  					{
  						strcat(transError," :DataSource Server Name ");
  						return  DS_TRANSLATION_ERROR;
  					}
  				}
  				break;
  			}
  		}
  		else if (retcode == ERROR_SUCCESS)
  			retcode = DS_NOT_FOUND;
  
  		error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  					   searchKey,
  					   0,
  					   KEY_READ,
  					   &keyHandle);
  		if (error == ERROR_SUCCESS)
  		{
  			m_DSLocation = HKLM_DSN; //HKLM
  			// Read AssociationService	Value
  			tmpWBuf[0] = L'\0';
  			keyValueLength = sizeof(tmpWBuf);;
  			error = RegQueryValueExW (keyHandle,
  							   L"Server",
  							   NULL,				// Reserved
  							   &keyValueType,
  							   (LPBYTE)tmpWBuf,
  							   &keyValueLength);
  			if (error != ERROR_SUCCESS)
  			{
  				error = RegQueryValueExW (keyHandle,
  							   L"AssociationService",
  							   NULL,				// Reserved
  							   &keyValueType,
  							   (LPBYTE)tmpWBuf,
  							   &keyValueLength);
  				if (error != ERROR_SUCCESS)
  				{
  					RegCloseKey( keyHandle);
  					if (retcode == ERROR_SUCCESS)
  						retcode = DS_AS_KEY_NOT_FOUND;
  				}
  				else
  				{
  					retcode = ERROR_SUCCESS;
  				}
  			}
  			else
  			{
  				retcode = ERROR_SUCCESS;
  			}
  			if (error == ERROR_SUCCESS)
  			{
  				// translate m_DSServer to UTF8
  				transError[0] = '\0';
  				if(wcslen((wchar_t*)tmpWBuf) > 0)
  				{
  					if (WCharToUTF8((wchar_t*) tmpWBuf, wcslen((wchar_t*)tmpWBuf), m_DSServer, sizeof(m_DSServer), &translen, transError)!= SQL_SUCCESS)
  					{
  						strcat(transError," :DataSource Server Name ");
  						return  DS_TRANSLATION_ERROR;
  					}
  				}
  				break;
  			}
  		}
  		else if (retcode == ERROR_SUCCESS)
  			retcode = DS_NOT_FOUND;
  	}
  
  	if (retcode != ERROR_SUCCESS)
  		return retcode;
  
  	//Read the Catalog Value in unicode
  	tmpWBuf[0] = L'\0';
  	keyValueLength = sizeof(tmpWBuf);
  	error = RegQueryValueExW (keyHandle,
  	                   L"Catalog",
  					   NULL,				// Reserved
  					   &keyValueType,
  					   (LPBYTE)tmpWBuf,
  					   &keyValueLength);
  	if (error != ERROR_SUCCESS)
  		m_DSCatalog[0] = '\0';
  	transError[0] = '\0';
  	//Convert Catalog Value to UTF-8
  	if(wcslen((wchar_t*)tmpWBuf) > 0)
  	{
  		if (WCharToUTF8((wchar_t*) tmpWBuf, wcslen((wchar_t*)tmpWBuf), m_DSCatalog, sizeof(m_DSCatalog), &translen, transError)!= SQL_SUCCESS)
  		{
  			strcat(transError," :DataSource Catalog Name ");
  			return  DS_TRANSLATION_ERROR;
  		}
  	}
  
  	// Read CtrlInferNCHAR Value
  	keyValueLength = sizeof(keyValueBuf);
  	error = RegQueryValueEx (keyHandle,
  	                   "CtrlInferNCHAR",
  					   NULL,				// Reserved
  					   &keyValueType,
  					   keyValueBuf,
  					   &keyValueLength);
  	if (error == ERROR_SUCCESS)
  	{
  		tempValue = atol((const char *)keyValueBuf);
  		if (tempValue)
  			m_DSCtrlInferNCHAR = TRUE;
  		else
  			m_DSCtrlInferNCHAR = FALSE;
  	}
  	else
  		m_DSCtrlInferNCHAR = TRUE;
  
  
  	// Read DataLang Value
  	keyValueLength = sizeof(keyValueBuf);
  	error = RegQueryValueEx (keyHandle,
  	                   "DataLang",
  					   NULL,				// Reserved
  					   &keyValueType,
  					   keyValueBuf,
  					   &keyValueLength);
  	if (error == ERROR_SUCCESS)
  	{
  		m_DSCharSet = atol((const char *)keyValueBuf);
  		m_DSDataLang = m_DSCharSet;
  		ODBCNLS_ValidateLanguage(&m_DSDataLang);
  	}
  	else	
  		m_DSDataLang = MAKELCID (MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), SORT_DEFAULT);
  
  	// Read ErrorMsgLang Value
  	keyValueLength = sizeof(keyValueBuf);
  	error = RegQueryValueEx (keyHandle,
  	                   "ErrorMsgLang",
  					   NULL,				// Reserved
  					   &keyValueType,
  					   keyValueBuf,
  					   &keyValueLength);
  	if (error == ERROR_SUCCESS)
  	{
  		m_DSErrorMsgLang = atol((const char *)keyValueBuf);
  		ODBCNLS_ValidateLanguage(&m_DSErrorMsgLang);
  	}
  	else	
  		m_DSErrorMsgLang = MAKELCID (MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), SORT_DEFAULT);
  
  	// Read FetchBufferSize
  	keyValueLength = sizeof(keyValueBuf);
  	error = RegQueryValueEx ( keyHandle
  	                   ,"FetchBufferSize"
  					   ,NULL				// Reserved
  					   ,&keyValueType
  					   ,keyValueBuf
  					   ,&keyValueLength);
  	if (error == ERROR_SUCCESS)
  	{	
  		if (strcmp((const char *)keyValueBuf, SYSTEM_DEFAULT) == 0)
  			m_DSFetchBufferSize = FETCH_BUFFER_SIZE_DEFAULT;
  		else
  			m_DSFetchBufferSize = atol((const char *)keyValueBuf) * 1024;
  	}
  	else
  		m_DSFetchBufferSize = FETCH_BUFFER_SIZE_DEFAULT;
  
  	//Read the Schema Value in unicode
  	tmpWBuf[0] = L'\0';
  	keyValueLength = sizeof(tmpWBuf);
  	error = RegQueryValueExW (keyHandle,
  	                   L"Schema",
  					   NULL,				// Reserved
  					   &keyValueType,
  					   (LPBYTE)tmpWBuf,
  					   &keyValueLength);
  	if (error != ERROR_SUCCESS)
  		m_DSSchema[0] = '\0';
  	transError[0] = '\0';
  	//Convert Schema Value to UTF-8
  	if(wcslen((wchar_t*)tmpWBuf) > 0)
  	{
  		if (WCharToUTF8((wchar_t*) tmpWBuf, wcslen((wchar_t*)tmpWBuf), m_DSSchema, sizeof(m_DSSchema), &translen, transError) != SQL_SUCCESS)
  		{
  			strcat(transError, " :DataSource Schema Name ");
  			return  DS_TRANSLATION_ERROR;
  		}
  	}
  	//customer specific change
  	if(m_DSSchema[0] == '\0')
  		gDrvrGlobal.noSchemaInDSN = true;
  
  	// Read SQL_ATTR_CONNECTION_TIMEOUT value
  	keyValueLength = sizeof(keyValueBuf);
  	error = RegQueryValueEx (keyHandle,
  	                   "SQL_ATTR_CONNECTION_TIMEOUT",
  					   NULL,				// Reserved
  					   &keyValueType,
  					   keyValueBuf,
  					   &keyValueLength);
  	if (error == ERROR_SUCCESS)
  	{	
  		if (strcmp((const char *)keyValueBuf, SYSTEM_DEFAULT) == 0)
  			m_DSConnectionTimeout = CONNECTION_TIMEOUT_DEFAULT;
  		else
  		if (strcmp((const char *)keyValueBuf, NO_TIMEOUT) == 0)
  			m_DSConnectionTimeout = 0;
  		else
  			m_DSConnectionTimeout = atol((const char *)keyValueBuf);
  	}
  	else
  		m_DSConnectionTimeout = CONNECTION_TIMEOUT_DEFAULT;
  		
  	// Read SQL_LOGIN_TIMEOUT value
  	keyValueLength = sizeof(keyValueBuf);
  	error = RegQueryValueEx (keyHandle,
  	                   "SQL_LOGIN_TIMEOUT",
  					   NULL,				// Reserved
  					   &keyValueType,
  					   keyValueBuf,
  					   &keyValueLength);
  	if (error == ERROR_SUCCESS)
  	{	
  		if (strcmp((const char *)keyValueBuf, SYSTEM_DEFAULT) == 0)
  			m_DSLoginTimeout = LOGIN_TIMEOUT_DEFAULT;
  		else
  		if (strcmp((const char *)keyValueBuf, NO_TIMEOUT) == 0)
  			m_DSLoginTimeout = 0;
  		else
  			m_DSLoginTimeout = atol((const char *)keyValueBuf);
  	}
  	else
  		m_DSLoginTimeout = LOGIN_TIMEOUT_DEFAULT;
  	
  	// Read SQL_QURRY_TIMEOUT value
  	keyValueLength = sizeof(keyValueBuf);
  	error = RegQueryValueEx (keyHandle,
  	                   "SQL_QUERY_TIMEOUT",
  					   NULL,				// Reserved
  					   &keyValueType,
  					   keyValueBuf,
  					   &keyValueLength);
  	if (error == ERROR_SUCCESS)
  	{	
  		if (strcmp((const char *)keyValueBuf, SYSTEM_DEFAULT) == 0)
  			m_DSQueryTimeout = QUERY_TIMEOUT_DEFAULT;
  		else
  		if (strcmp((const char *)keyValueBuf, NO_TIMEOUT) == 0)
  			m_DSQueryTimeout = 0;
  		else
  		{
  			m_DSQueryTimeout = atol((const char *)keyValueBuf);
  			if(m_DSQueryTimeout != 0 && m_DSQueryTimeout < 30)
  				m_DSQueryTimeout = 30;
  		}
  	}
  	else
  		m_DSQueryTimeout = QUERY_TIMEOUT_DEFAULT;
  	
  	// Read TranslationDLL Value
  	keyValueLength = sizeof(m_DSTranslationDLL);
  	error = RegQueryValueEx (keyHandle,
  	                   "TranslationDLL",
  					   NULL,				// Reserved
  					   &keyValueType,
  					   (LPBYTE)m_DSTranslationDLL,
  					   &keyValueLength);
  	if (error != ERROR_SUCCESS)
  		m_DSTranslationDLL[0] = '\0';
  
  	// Read TranslationOption Value
  	keyValueLength = sizeof(keyValueBuf);
  	error = RegQueryValueEx (keyHandle,
  	                   "TranslationOption",
  					   NULL,				// Reserved
  					   &keyValueType,
  					   keyValueBuf,
  					   &keyValueLength);
  	if (error == ERROR_SUCCESS)
  		m_DSTranslationOption = atol((const char *)keyValueBuf);
  	else
  		m_DSTranslationOption = 0;
  
  	// Read ReplacementChar Value
  	keyValueLength = sizeof(m_DSReplacementChar);
  	error = RegQueryValueEx (keyHandle,
  	                   "ReplacementCharacter",
  					   NULL,				// Reserved
  					   &keyValueType,
  					   (LPBYTE)m_DSReplacementChar,
  					   &keyValueLength);
  	if (error != ERROR_SUCCESS)
  		m_DSReplacementChar[0] = '\0';
  
  // Read select rowsets value
  // It is internal parameter not exposed through the administrator, where we define the behavior for rowset or non-rowset
  
  	keyValueLength = sizeof(keyValueBuf);
  	error = RegQueryValueEx (keyHandle,
  	                   "SelectRowsets",
  					   NULL,				// Reserved
  					   &keyValueType,
  					   keyValueBuf,
  					   &keyValueLength);
  
  	if (error == ERROR_SUCCESS)
  	{
  		tempValue = atol((const char *)keyValueBuf);
  		if (tempValue)
  			m_DSSelectRowsets = TRUE;
  		else
  			m_DSSelectRowsets = FALSE;
  	}
  	else
  		m_DSSelectRowsets = TRUE;
  
  // Compression 
  
  	keyValueLength = sizeof(keyValueBuf);
  	error = RegQueryValueEx (keyHandle,
  	                   "Compression",
  					   NULL,				// Reserved
  					   &keyValueType,
  					   keyValueBuf,
  					   &keyValueLength);
  
  	if (error == ERROR_SUCCESS){
  		if(_stricmp((const char *)keyValueBuf,SYSTEM_DEFAULT)==0){
  				m_DSIOCompression = 0;
  		}
  		else if(_stricmp((const char *)keyValueBuf,"no compression")==0){
  			m_DSIOCompression = COMP_NO_COMPRESSION;
  		}
  		else if(_stricmp((const char *)keyValueBuf,"best speed")==0){
  			m_DSIOCompression = COMP_BEST_SPEED;
  		}
  		else if(_stricmp((const char *)keyValueBuf,"best compression")==0){
  			m_DSIOCompression = COMP_BEST_COMPRESSION;
  		}
  		else if(_stricmp((const char *)keyValueBuf,"balance")==0){
  			m_DSIOCompression = COMP_DEFAULT;
  		}
  		else{
  			m_DSIOCompression = atol((const char *)keyValueBuf);
  		}
  	}
  	else
  		m_DSIOCompression = 0;
  
  	//get threshold of compression ,default is 1000
  	keyValueLength = sizeof(keyValueBuf);
  	error = RegQueryValueEx(keyHandle,
  		"CompressionThreshold",
  		NULL,				// Reserved
  		&keyValueType,
  		keyValueBuf,
  		&keyValueLength);
  
  	if (error == ERROR_SUCCESS)
  	{
  		if (strcmp((const char *)keyValueBuf, SYSTEM_DEFAULT) == 0)
  			m_DSIOCompressionThreshold = IOCOMPRESSION_DEFAULT;
  		else
  		{
  			m_DSIOCompressionThreshold = atol((const char *)keyValueBuf);
  		}
  
  	}
  	else
  		m_DSIOCompressionThreshold = IOCOMPRESSION_DEFAULT;
  
  	keyValueLength = sizeof(keyValueBuf);
  	error = RegQueryValueEx(keyHandle,
  						"RowsetErrorRecovery",
  						NULL,
  						&keyValueType,
  						keyValueBuf,
  						&keyValueLength);
  
  	if (error == ERROR_SUCCESS)
  	{
  		if (atol((const char *)keyValueBuf))
  			m_DSRowsetErrorRecovery = TRUE;
  		else
  			m_DSRowsetErrorRecovery = FALSE;
  	}
  	else
  		m_DSRowsetErrorRecovery = TRUE;
  
  	//Read the ServerDSN Value in unicode
  	tmpWBuf[0] = L'\0';
  	keyValueLength = sizeof(tmpWBuf);
  	error = RegQueryValueExW (keyHandle,
  	                   L"ServerDSN",
  					   NULL,				// Reserved
  					   &keyValueType,
  					   (LPBYTE)tmpWBuf,
  					   &keyValueLength);
  	if (error != ERROR_SUCCESS)
  		m_DSServerDSName[0] = '\0';
  	transError[0] = '\0';
  	//Convert ServerDSN Value to UTF-8
  	if(wcslen((wchar_t*)tmpWBuf) > 0)
  	{
  		if (WCharToUTF8((wchar_t*) tmpWBuf, wcslen((wchar_t*)tmpWBuf), m_DSServerDSName, sizeof(m_DSServerDSName), &translen, transError) != SQL_SUCCESS)
  		{
  			strcat(transError, " :DataSource ServerDSName ");
  			return  DS_TRANSLATION_ERROR;
  		}
  	}
  
  	keyValueLength = sizeof(keyValueBuf);
  	error = RegQueryValueEx(keyHandle,
  						"MapErrors",
  						NULL,
  						&keyValueType,
  						keyValueBuf,
  						&keyValueLength);
  
  	if (error == ERROR_SUCCESS)
  	{
  		if (atol((const char *)keyValueBuf))
  			GTransport.bMapErrors = TRUE;
  		else
  			GTransport.bMapErrors = FALSE;
  	}
  	else
  		GTransport.bMapErrors = TRUE;
  
  // FlushFetchData Y/N (default is N)
  // It is internal parameter not exposed through the administrator,
  // where we define the behavior for ATC query driver which cannot handle huge data being returned.
  
  	keyValueLength = sizeof(keyValueBuf);
  	error = RegQueryValueEx (keyHandle,
  	                   "FlushFetchData",
  					   NULL,				// Reserved
  					   &keyValueType,
  					   keyValueBuf,
  					   &keyValueLength);
  
  	if (error == ERROR_SUCCESS)
  	{
  		if (keyValueBuf[0] == 'N')
  			m_DSFlushFetchData = FALSE;
  		else
  			m_DSFlushFetchData = TRUE;
  	}
  	else
  		m_DSFlushFetchData = FALSE;
  
  	//Read the ServiceName Value in unicode
  	tmpWBuf[0] = L'\0';
  	keyValueLength = sizeof(tmpWBuf);
  	error = RegQueryValueExW (keyHandle,
  	                   L"ServiceName",
  					   NULL,				// Reserved
  					   &keyValueType,
  					   (LPBYTE)tmpWBuf,
  					   &keyValueLength);
  	if (error != ERROR_SUCCESS)
  		m_DSServiceName[0] = '\0';
  	//Convert ServiceName Value to UTF-8
  	if(wcslen((wchar_t*)tmpWBuf) > 0)
  	{
  		if (WCharToUTF8((wchar_t*) tmpWBuf, wcslen((wchar_t*)tmpWBuf), m_DSServiceName, sizeof(m_DSServiceName), &translen, transError) != SQL_SUCCESS)
  		{
  			strcat(transError, " :DataSource ServiceName ");
  			return  DS_TRANSLATION_ERROR;
  		}
  	}
  
  	RegCloseKey( keyHandle);
  	return ERROR_SUCCESS;
  }
  
  void CDataSource::updateDSValues(short DSNType, CONNECT_FIELD_ITEMS *connectFieldItems,
  								 CONNECT_KEYWORD_TREE *keywordTree)
  {
  	long	tempValue;
  	char	AttrValue[256];
  	short	i;
  
  	if (DSNType == DRIVER_KW_DSN)
  		m_DSName[0] = '\0';
  	strcpy(m_DSServer, connectFieldItems->server);
  	strcpy(m_DSCatalog, connectFieldItems->catalog);
  	strcpy(m_DSSchema, connectFieldItems->schema);
  	
  	for (i = KEY_SCHEMA+1 ; i < KEY_MAX ; i++)
  	{
  		if (keywordTree[i].AttrRank != 0)
  		{
  			strcpyUTF8(AttrValue, keywordTree[i].AttrValue, sizeof(AttrValue), keywordTree[i].AttrLength);
  			switch (i)
  			{
  			case KEY_CTRLINFERNCHAR:
  				tempValue = atol(AttrValue);
  				if (tempValue)
  					m_DSCtrlInferNCHAR = TRUE;
  				else
  					m_DSCtrlInferNCHAR = FALSE;
  				break;
  			case KEY_DATALANG:
  				m_DSCharSet = atol(keywordTree[KEY_DATALANG].AttrValue);
  				m_DSDataLang = m_DSCharSet;
  				ODBCNLS_ValidateLanguage(&m_DSDataLang);
  				break;
  			case KEY_ERRORMSGLANG:
  				m_DSErrorMsgLang = atol(AttrValue);
  				ODBCNLS_ValidateLanguage(&m_DSErrorMsgLang);
  				break;
  			case KEY_FETCHBUFFERSIZE:
  				if (_stricmp(AttrValue, SYSTEM_DEFAULT) == 0)
  					m_DSFetchBufferSize = FETCH_BUFFER_SIZE_DEFAULT;
  				else
  					m_DSFetchBufferSize = atol(AttrValue);
  				break;
  			case KEY_SQL_ATTR_CONNECTION_TIMEOUT:
  				if (_stricmp(AttrValue, SYSTEM_DEFAULT) == 0)
  					m_DSConnectionTimeout = CONNECTION_TIMEOUT_DEFAULT;
  				else
  					m_DSConnectionTimeout = atol(AttrValue);
  				break;
  			case KEY_SQL_LOGIN_TIMEOUT:
  				if (_stricmp(AttrValue, SYSTEM_DEFAULT) == 0)
  					m_DSLoginTimeout = LOGIN_TIMEOUT_DEFAULT;
  				else
  					m_DSLoginTimeout = atol(AttrValue);
  				break;
  			case KEY_SQL_QUERY_TIMEOUT:
  				if (_stricmp(AttrValue, SYSTEM_DEFAULT) == 0)
  					m_DSQueryTimeout = QUERY_TIMEOUT_DEFAULT;
  				else
  					m_DSQueryTimeout = atol(AttrValue);
  				break;
  			case KEY_TRANSLATIONDLL:
  				strcpyUTF8(m_DSTranslationDLL, AttrValue, sizeof(m_DSTranslationDLL));
  				break;
  			case KEY_TRANSLATIONOPTION:
  				m_DSTranslationOption = atol(AttrValue);
  				break;
  			case KEY_REPLACEMENTCHAR:
  				strcpyUTF8(m_DSReplacementChar, AttrValue, sizeof(m_DSReplacementChar));
  				break;
  			case KEY_SDSN:
  				strcpyUTF8(m_DSServerDSName, AttrValue, sizeof(m_DSServerDSName));
  				break;
  			case KEY_SN:
  				strcpyUTF8(m_DSServiceName, AttrValue, sizeof(m_DSServiceName));
  				break;
  			case KEY_SESSION:
  				strcpyUTF8(m_DSSession, AttrValue, sizeof(m_DSSession));
  				break;
  			case KEY_APPLICATION:
  				strcpyUTF8(m_DSApplication, AttrValue, sizeof(m_DSApplication));
  				break;
  			case KEY_ROLENAME:
  				strcpyUTF8(m_DSRoleName, AttrValue, sizeof(m_DSRoleName));
  				break;
  			case KEY_CERTIFICATEDIR:
  				strcpyUTF8(m_DSCertificateDir, AttrValue, sizeof(m_DSCertificateDir));
  				break;
  			case KEY_CERTIFICATEFILE:
  				strcpyUTF8(m_DSCertificateFile, AttrValue, sizeof(m_DSCertificateFile));
  				break;
  			case KEY_CERTIFICATEFILE_ACTIVE:
  				strcpyUTF8(m_DSCertificateFileActive, AttrValue, sizeof(m_DSCertificateFileActive));
  				break;
  			case KEY_COMPRESSION:
  				if(_stricmp(AttrValue,SYSTEM_DEFAULT)==0){
  					m_DSIOCompression = 0;
  				}
  				else if(_stricmp(AttrValue,"no compression")==0){
  					m_DSIOCompression = COMP_NO_COMPRESSION;
  				}
  				else if(_stricmp(AttrValue,"best speed")==0){
  					m_DSIOCompression = COMP_BEST_SPEED;
  				}
  				else if(_stricmp(AttrValue,"best compression")==0){
  					m_DSIOCompression = COMP_BEST_COMPRESSION;
  				}
  				else if(_stricmp(AttrValue,"balance")==0){
  					m_DSIOCompression = COMP_DEFAULT;
  				}
  				else{
  					m_DSIOCompression = atol(AttrValue);
  				}
  				break;
  			case KEY_COMPRESSIONTHRESHOLD:
  				if (stricmp(AttrValue, SYSTEM_DEFAULT) == 0){
  					  m_DSIOCompressionThreshold = IOCOMPRESSION_DEFAULT;
  				}
  				else
  				{
  				         m_DSIOCompressionThreshold = atol((const char *)AttrValue);
  				}
  				break;
  			default:
  				break;
  			}
  		}
  	}
  }
  