Пример #1
0
BOOL APIENTRY
ConfigDSNW (
    HWND hWinParent,
    WORD fRequest,
    LPCTSTR lpszDriver,
    LPCTSTR lpszAttributes)
{
  TCHAR szNewDSN[MAX_DSN_LEN + 1];
  TCHAR szDSN[MAX_DSN_LEN + 1];
  TKVList props;
  TSetupDlg setupDlg (props);

  props.FromAttributes (lpszAttributes);
  if (props.Get (_T("DSN"), szDSN, NUMCHARS (szDSN)))
    {
      props.ReadODBCIni (szDSN, _virtuoso_tags);
      props.FromAttributes (lpszAttributes);
    }

  if (fRequest == ODBC_REMOVE_DSN)
    {
      SQLRemoveDSNFromIni (szDSN);
    }
  else if (fRequest == ODBC_CONFIG_DSN || fRequest == ODBC_ADD_DSN)
    {
      if (hWinParent)
        {
          setupDlg.m_bFileDSN = FALSE;
          if (setupDlg.RunModal (g_hInstance, IDD_CONFIGDSN, hWinParent) == IDOK)
	    {
	      if (props.Get (_T("DSN"), szNewDSN, NUMCHARS (szNewDSN)))
	        {
	          props.Undefine (_T("PWD"));
	          SQLWriteDSNToIni (szNewDSN, lpszDriver);
	          props.WriteODBCIni (szNewDSN, _virtuoso_tags);

	          /* If the DSN has changed, delete the old one */
	          if (fRequest == ODBC_CONFIG_DSN && _tcsicmp (szDSN, szNewDSN))
		    SQLRemoveDSNFromIni (szDSN);
	        }
	    }
        }
      else
        {
	  if (props.Get (_T("DSN"), szNewDSN, NUMCHARS (szNewDSN)))
	    {
	       props.Undefine (_T("PWD"));
	       SQLWriteDSNToIni (szNewDSN, lpszDriver);
	       props.WriteODBCIni (szNewDSN, _virtuoso_tags);

	       /* If the DSN has changed, delete the old one */
	       if (fRequest == ODBC_CONFIG_DSN && _tcsicmp (szDSN, szNewDSN))
	          SQLRemoveDSNFromIni (szDSN);
	    }
        }
    }

  return TRUE;
}
Пример #2
0
void COdbcDS::UpdateDS(const char* pNewDriverName, int iType, CDSList& DSList)
{
	int count = DSList.getCount();
	int length = sizeof(PRIV_PROFILE) / MAXKEYLEN;
	char* DSName = NULL;
	char* DSAttVal = NULL;

	// Set the config mode to the desired type.
	UWORD oldMode, newMode;

	if (iType == COdbcDS::DS_TYPE_SYS)
	{
		newMode = ODBC_SYSTEM_DSN;
	}
	else
	{
		newMode = ODBC_USER_DSN;
	}

	SQLGetConfigMode(&oldMode);
	SQLSetConfigMode(newMode);

	for (int i = 0; i < count; i++)
	{
		DSName = DSList.getAt(i);

		// Remove the old data sources
		SQLRemoveDSNFromIni(DSName);

		// Add the new data source
		if (TRUE != SQLWriteDSNToIni(DSName, pNewDriverName))
		{
			// Restore old config mode.
			SQLSetConfigMode(oldMode);
			throw -1;
		}

		// Configure the new data source using previous information.
		for (int index = 0; index < length; index++)
		{
			DSAttVal = DSList.getAttribValue(i, PRIV_PROFILE[index]);

			if (TRUE != SQLWritePrivateProfileString(DSName,
							PRIV_PROFILE[index], DSAttVal, ODBC_INI))
			{
				// Restore old config mode.
				SQLSetConfigMode(oldMode);
				throw -2;
			}

			delete [] DSAttVal;
		}

		delete [] DSName;
	}

	// Restore old config mode.
	SQLSetConfigMode(oldMode);
}
Пример #3
0
/*--------
 * SetDSNAttributes
 *
 *	Description:	Write data source attributes to ODBC.INI
 *	Input	 :	hwnd - Parent window handle (plus globals)
 *	Output	 :	TRUE if successful, FALSE otherwise
 *--------
 */
BOOL		INTFUNC
SetDSNAttributes(HWND hwndParent, LPSETUPDLG lpsetupdlg, DWORD *errcode)
{
	LPCSTR		lpszDSN;		/* Pointer to data source name */

	lpszDSN = lpsetupdlg->ci.dsn;

	if (errcode)
		*errcode = 0;
	/* Validate arguments */
	if (lpsetupdlg->fNewDSN && !*lpsetupdlg->ci.dsn)
		return FALSE;

	/* Write the data source name */
	if (!SQLWriteDSNToIni(lpszDSN, lpsetupdlg->lpszDrvr))
	{
		RETCODE	ret = SQL_ERROR;
		DWORD	err = SQL_ERROR;
		char    szMsg[SQL_MAX_MESSAGE_LENGTH];

#if (ODBCVER >= 0x0300)
		ret = SQLInstallerError(1, &err, szMsg, sizeof(szMsg), NULL);
#endif /* ODBCVER */
		if (hwndParent)
		{
			char		szBuf[MAXPGPATH];

			if (SQL_SUCCESS != ret)
			{
				LoadString(s_hModule, IDS_BADDSN, szBuf, sizeof(szBuf));
				wsprintf(szMsg, szBuf, lpszDSN);
			}
			LoadString(s_hModule, IDS_MSGTITLE, szBuf, sizeof(szBuf));
			MessageBox(hwndParent, szMsg, szBuf, MB_ICONEXCLAMATION | MB_OK);
		}
		if (errcode)
			*errcode = err;
		return FALSE;
	}

	/* Update ODBC.INI */
	writeDriverCommoninfo(ODBC_INI, lpsetupdlg->ci.dsn, &(lpsetupdlg->ci.drivers));
	writeDSNinfo(&lpsetupdlg->ci);

	/* If the data source name has changed, remove the old name */
	if (lstrcmpi(lpsetupdlg->szDSN, lpsetupdlg->ci.dsn))
		SQLRemoveDSNFromIni(lpsetupdlg->szDSN);
	return TRUE;
}
Пример #4
0
BOOL INSTAPI SQLWriteDSNToIniW        (LPCWSTR     lpszDSN,
                                      LPCWSTR     lpszDriver)
{
	char *drv, *dsn;
	BOOL ret;

	dsn = _single_string_alloc_and_copy( lpszDSN );
	drv = _single_string_alloc_and_copy( lpszDriver );

	ret = SQLWriteDSNToIni( dsn, drv );

	free( dsn );
	free( drv );

	return ret;
}
Пример #5
0
BOOL INSTAPI
ConfigDSN (
    HWND	  hwndParent,
    WORD	  fRequest,
    LPCSTR	  lpszDriver,
    LPCSTR	  lpszAttributes)
{
  char *dsn = NULL, *connstr = NULL, *curr, *cour = NULL;
  char dsnread[4096] = { 0 };
  char prov[4096] = { 0 };
  int driver_type = -1, flags = 0;
  BOOL retcode = FALSE;
  UWORD confMode = ODBC_USER_DSN;

  /* Map the request User/System */
  if (fRequest < ODBC_ADD_DSN || fRequest > ODBC_REMOVE_DSN)
    {
      SQLPostInstallerError (ODBC_ERROR_INVALID_REQUEST_TYPE, NULL);
      goto done;
    }

  if (!lpszDriver || !STRLEN (lpszDriver))
    {
      SQLPostInstallerError (ODBC_ERROR_INVALID_NAME, NULL);
      goto done;
    }

  /* Retrieve the config mode */
  SQLGetConfigMode (&confMode);

  /* Retrieve the DSN if one exist */
  for (curr = (LPSTR) lpszAttributes; curr && *curr;
      curr += (STRLEN (curr) + 1))
    {
      if (!strncmp (curr, "DSN=", STRLEN ("DSN=")))
	{
	  dsn = curr + STRLEN ("DSN=");
	  break;
	}
    }

  /* Retrieve the corresponding driver */
  if (strstr (lpszDriver, "OpenLink") || strstr (lpszDriver, "Openlink")
      || strstr (lpszDriver, "oplodbc"))
    {
      driver_type = 0;

      for (curr = (LPSTR) lpszAttributes, cour = prov; curr && *curr;
	  curr += (STRLEN (curr) + 1), cour += (STRLEN (cour) + 1))
	{
	  if (!strncasecmp (curr, "Host=", STRLEN ("Host="))
	      && STRLEN (curr + STRLEN ("Host=")))
	    {
	      STRCPY (cour, curr);
	      flags |= 0x1;
	      continue;
	    }
	  if (!strncasecmp (curr, "ServerType=", STRLEN ("ServerType="))
	      && STRLEN (curr + STRLEN ("ServerType=")))
	    {
	      STRCPY (cour, curr);
	      flags |= 0x2;
	      continue;
	    }
	  STRCPY (cour, curr);
	}

      if (cour && !(flags & 1))
	{
	  STRCPY (cour, "Host=localhost\0");
	  cour += (STRLEN (cour) + 1);
	}

      if (cour && !(flags & 2))
	{
	  STRCPY (cour, "ServerType=Proxy\0");
	  cour += (STRLEN (cour) + 1);
	}

      if (cour)
	*cour = 0;
    }
  else if ((strstr (lpszDriver, "Virtuoso")
	  || strstr (lpszDriver, "virtodbc")))
    driver_type = 1;

  /* For each request */
  switch (fRequest)
    {
    case ODBC_ADD_DSN:
      /* Check if the DSN with this name already exists */

      SQLSetConfigMode (confMode);
#ifdef WIN32
      if (hwndParent && dsn
	  && SQLGetPrivateProfileString ("ODBC 32 bit Data Sources", dsn, "",
	      dsnread, sizeof (dsnread), NULL)
	  && !create_confirm (hwndParent, dsn,
	      "Are you sure you want to overwrite this DSN ?"))
#else
      if (hwndParent && dsn
	  && SQLGetPrivateProfileString ("ODBC Data Sources", dsn, "",
	      dsnread, sizeof (dsnread), NULL)
	  && !create_confirm (hwndParent, dsn,
	      "Are you sure you want to overwrite this DSN ?"))
#endif
	goto done;

      /* Call the right setup function */
      connstr =
	  create_gensetup (hwndParent, dsn,
	  STRLEN (prov) ? prov : lpszAttributes, TRUE);

      /* Check output parameters */
      if (!connstr)
	{
	  SQLPostInstallerError (ODBC_ERROR_OUT_OF_MEM, NULL);
	  goto done;
	}

      if (connstr == (LPSTR) - 1L)
	goto done;

      /* Add the DSN to the ODBC Data Sources */
      SQLSetConfigMode (confMode);
      if (!SQLWriteDSNToIni (dsn = connstr + STRLEN ("DSN="), lpszDriver))
	goto done;

      /* Add each keyword and values */
      for (curr = connstr; *curr; curr += (STRLEN (curr) + 1))
	{
	  if (strncmp (curr, "DSN=", STRLEN ("DSN=")))
	    {
	      STRCPY (dsnread, curr);
	      cour = strchr (dsnread, '=');
	      if (cour)
		*cour = 0;
	      SQLSetConfigMode (confMode);
	      if (!SQLWritePrivateProfileString (dsn, dsnread, (cour
			  && STRLEN (cour + 1)) ? cour + 1 : NULL, NULL))
		goto done;
	    }
	}

      break;

    case ODBC_CONFIG_DSN:

      if (!dsn || !STRLEN (dsn))
	{
	  SQLPostInstallerError (ODBC_ERROR_INVALID_KEYWORD_VALUE, NULL);
	  goto done;
	}

      /* Call the right setup function */
      connstr = create_gensetup (hwndParent, dsn,
	  STRLEN (prov) ? prov : lpszAttributes, FALSE);

      /* Check output parameters */
      if (!connstr)
	{
	  SQLPostInstallerError (ODBC_ERROR_OUT_OF_MEM, NULL);
	  goto done;
	}

      if (connstr == (LPSTR) - 1L)
	goto done;

      /* Compare if the DSN changed */
      if (strcmp (connstr + STRLEN ("DSN="), dsn))
	{
	  /* Remove the previous DSN */
	  SQLSetConfigMode (confMode);
	  if (!SQLRemoveDSNFromIni (dsn))
	    goto done;
	  /* Add the new DSN section */
	  SQLSetConfigMode (confMode);
	  if (!SQLWriteDSNToIni (dsn = connstr + STRLEN ("DSN="), lpszDriver))
	    goto done;
	}

      /* Add each keyword and values */
      for (curr = connstr; *curr; curr += (STRLEN (curr) + 1))
	{

	  if (strncmp (curr, "DSN=", STRLEN ("DSN=")))
	    {
	      STRCPY (dsnread, curr);
	      cour = strchr (dsnread, '=');
	      if (cour)
		*cour = 0;
	      SQLSetConfigMode (confMode);
	      if (!SQLWritePrivateProfileString (dsn, dsnread, (cour
			  && STRLEN (cour + 1)) ? cour + 1 : NULL, NULL))
		goto done;
	    }
	}

      break;

    case ODBC_REMOVE_DSN:
      if (!dsn || !STRLEN (dsn))
	{
	  SQLPostInstallerError (ODBC_ERROR_INVALID_KEYWORD_VALUE, NULL);
	  goto done;
	}

      /* Just remove the DSN */
      SQLSetConfigMode (confMode);
      if (!SQLRemoveDSNFromIni (dsn))
	goto done;
      break;
    };

quit:
  retcode = TRUE;

done:
  if (connstr && connstr != (LPSTR) - 1L && connstr != lpszAttributes
      && connstr != prov)
    free (connstr);

  return retcode;
}
Пример #6
0
bool CPropSheet::UpdateDSN( void )
{
	char* lpszDSN;
	char  szBuf[ _MAX_PATH];

	lpszDSN = aAttr[ KEY_DSN].szAttr;

// if the data source name has changed, remove the old name
	if( !bNewDSN && strcmp( szDSN, lpszDSN) != 0)
	{
		SQLRemoveDSNFromIni( szDSN);
// remove File Data Source Name
		DeleteFileDSN( szDSN );
	}

	if(strcmp( szDSN, lpszDSN )!=0)
	{
		WritePrivateProfileString( lpszDSN,	INI_KDESC, aAttr[ KEY_DESC].szAttr,	ODBC_INI);
		WritePrivateProfileString( lpszDSN,	INI_KSN, aAttr[ KEY_SERVICE_NAME].szAttr,	ODBC_INI);
// update File DSN
		lstrcpy(szBuf, lpszDSN );
		lstrcat(szBuf, " (not sharable)");
		SQLWriteFileDSN( szBuf, "ODBC", "DSN", lpszDSN );
		SQLWritePrivateProfileString( lpszDSN,	INI_KDESC, aAttr[ KEY_DESC].szAttr,	ODBC_INI);
		SQLWritePrivateProfileString( lpszDSN,	INI_KSN, aAttr[ KEY_SERVICE_NAME].szAttr,	ODBC_INI);
	}

// write data source name
	if( !SQLWriteDSNToIni( lpszDSN, lpszDrvr))
	{
		char  szMsg[ MAXPATHLEN];
		CString szBuf;
			
		szBuf.LoadString(IDS_BADDSN);
		wsprintf( szMsg, szBuf, lpszDSN);			
		AfxMessageBox( szMsg);
		return FALSE;
	}

// update ODBC.INI
// save the value if the data source is new, edited, or explicitly supplied
	WritePrivateProfileString( lpszDSN,	INI_KDESC, aAttr[ KEY_DESC].szAttr,	ODBC_INI);
	WritePrivateProfileString( lpszDSN,	INI_KSN, aAttr[ KEY_SERVICE_NAME].szAttr,	ODBC_INI);
// update File DSN
	lstrcpy(szBuf, lpszDSN );
	lstrcat(szBuf, " (not sharable)");
	SQLWriteFileDSN( szBuf, "ODBC", "DSN", lpszDSN );
	SQLWritePrivateProfileString( lpszDSN,	INI_KDESC, aAttr[ KEY_DESC].szAttr,	ODBC_INI);
	SQLWritePrivateProfileString( lpszDSN,	INI_KSN, aAttr[ KEY_SERVICE_NAME].szAttr,	ODBC_INI);

// the following are the localization (internationalization) attributes
	WritePrivateProfileString( lpszDSN,	INI_ERRORLANG, aAttr[ KEY_ERRORLANG].szAttr, ODBC_INI);
	SQLWritePrivateProfileString( lpszDSN,	INI_ERRORLANG, aAttr[ KEY_ERRORLANG].szAttr, ODBC_INI);

	WritePrivateProfileString( lpszDSN,	INI_DATALANG, aAttr[ KEY_DATALANG].szAttr, ODBC_INI);
	SQLWritePrivateProfileString( lpszDSN,	INI_DATALANG, aAttr[ KEY_DATALANG].szAttr, ODBC_INI);

// Association Service (IP Address and Port Number)
	wsprintf(szBuf, "%s%s/%s", TCP_STR, aAttr[ KEY_IPADDRESS].szAttr, aAttr[ KEY_PORTNUM].szAttr);

	WritePrivateProfileString( lpszDSN,	INI_NETWORK, szBuf, ODBC_INI);
	SQLWritePrivateProfileString( lpszDSN,	INI_NETWORK, szBuf, ODBC_INI);

	WritePrivateProfileString( lpszDSN,	INI_LOGIN, aAttr[ KEY_LOGIN].szAttr, ODBC_INI);
	SQLWritePrivateProfileString( lpszDSN,	INI_LOGIN, aAttr[ KEY_LOGIN].szAttr, ODBC_INI);

	WritePrivateProfileString( lpszDSN,	INI_CONNECTION, aAttr[ KEY_CONNECTION].szAttr, ODBC_INI);
	SQLWritePrivateProfileString( lpszDSN,	INI_CONNECTION, aAttr[ KEY_CONNECTION].szAttr, ODBC_INI);

	WritePrivateProfileString( lpszDSN,	INI_QUERY, aAttr[ KEY_QUERY].szAttr, ODBC_INI);
	SQLWritePrivateProfileString( lpszDSN,	INI_QUERY, aAttr[ KEY_QUERY].szAttr, ODBC_INI);

	WritePrivateProfileString( lpszDSN,	INI_CATALOG, aAttr[ KEY_CATALOG].szAttr, ODBC_INI);
	SQLWritePrivateProfileString( lpszDSN,	INI_CATALOG, aAttr[ KEY_CATALOG].szAttr, ODBC_INI);
	
	WritePrivateProfileString( lpszDSN,	INI_SCHEMA, aAttr[ KEY_SCHEMA].szAttr, ODBC_INI);
	SQLWritePrivateProfileString( lpszDSN,	INI_SCHEMA, aAttr[ KEY_SCHEMA].szAttr, ODBC_INI);

	WritePrivateProfileString( lpszDSN,	INI_TRANSLATION_DLL, aAttr[ KEY_TRANSLATION_DLL].szAttr, ODBC_INI);
	SQLWritePrivateProfileString( lpszDSN,	INI_TRANSLATION_DLL, aAttr[ KEY_TRANSLATION_DLL].szAttr, ODBC_INI);

	WritePrivateProfileString( lpszDSN,	INI_TRANSLATION_OPTION, aAttr[ KEY_TRANSLATION_OPTION].szAttr, ODBC_INI);
	SQLWritePrivateProfileString( lpszDSN,	INI_TRANSLATION_OPTION, aAttr[ KEY_TRANSLATION_OPTION].szAttr, ODBC_INI);

	WritePrivateProfileString( lpszDSN,	INI_FETCH_BUFFER_SIZE, aAttr[ KEY_FETCH_BUFFER_SIZE].szAttr, ODBC_INI);
	SQLWritePrivateProfileString( lpszDSN,	INI_FETCH_BUFFER_SIZE, aAttr[ KEY_FETCH_BUFFER_SIZE].szAttr, ODBC_INI);

	WritePrivateProfileString( lpszDSN,	INI_REPLACEMENT_CHAR, aAttr[ KEY_REPLACEMENT_CHAR].szAttr, ODBC_INI);
	SQLWritePrivateProfileString( lpszDSN,	INI_REPLACEMENT_CHAR, aAttr[ KEY_REPLACEMENT_CHAR].szAttr, ODBC_INI);

	WritePrivateProfileString( lpszDSN,	INI_COMPRESSION, aAttr[ KEY_COMPRESSION].szAttr, ODBC_INI);
	SQLWritePrivateProfileString( lpszDSN,	INI_COMPRESSION, aAttr[ KEY_COMPRESSION].szAttr, ODBC_INI);

	WriteTraceRegistry( INI_TRACE_FILE,aAttr[ KEY_TRACE_FILE].szAttr);
	
	WriteTraceRegistry( INI_TRACE_FLAGS,aAttr[ KEY_TRACE_FLAGS].szAttr);

	return TRUE;
}
Пример #7
0
/**
 * Add, remove, or modify a data source
 * \param hwndParent parent for dialog, NULL for batch ops
 * \param fRequest request type
 * \param lpszDriver driver name (for humans, not DLL name)
 * \param lpszAttributes attribute list
 */
BOOL INSTAPI
ConfigDSN(HWND hwndParent, WORD fRequest, LPCSTR lpszDriver, LPCSTR lpszAttributes)
{
	int result;
	DSNINFO *di;
	const char *errmsg;

	/*
	 * Initialize Windows sockets.  This is necessary even though
	 * ConfigDSN() only looks up addresses and names, and never actually
	 * uses any sockets.
	 */
	INITSOCKET();

	/* Create a blank login struct */
	di = alloc_dsninfo();

	/*
	 * Parse the attribute string.  If this contains a DSN name, then it
	 * also reads the current parameters of that DSN.
	 */
	parse_wacky_dsn_string(lpszAttributes, di);

	/* Maybe allow the user to edit it */
	if (hwndParent && fRequest != ODBC_REMOVE_DSN) {
		result = DialogBoxParam(hinstFreeTDS, MAKEINTRESOURCE(IDD_DSN), hwndParent, (DLGPROC) DSNDlgProc, (LPARAM) di);
		if (result < 0) {
			DWORD errorcode = GetLastError();
			char buf[1000];

			FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorcode, 0, buf, 1000, NULL);
		}

		/* if user hit [Cancel] then clean up and return FALSE */
		if (result == 0) {
			goto Fail;
		}
	}

	switch (fRequest) {
	case ODBC_ADD_DSN:
		errmsg = validate(di);
		if (errmsg != NULL) {
			SQLPostInstallerError(ODBC_ERROR_REQUEST_FAILED, errmsg);
			goto Fail;
		}
		if (!SQLWriteDSNToIni(tds_dstr_cstr(&di->dsn), lpszDriver)) {
			goto Fail;
		}
		if (!write_all_strings(di)) {
			goto Fail;
		}
		break;
	case ODBC_CONFIG_DSN:
		errmsg = validate(di);
		if (errmsg != NULL) {
			SQLPostInstallerError(ODBC_ERROR_REQUEST_FAILED, errmsg);
			goto Fail;
		}

		/*
		 * if the DSN name has changed, then delete the old entry and
		 * add the new one.
		 */
		if (strcasecmp(tds_dstr_cstr(&di->origdsn), tds_dstr_cstr(&di->dsn))) {
			if (!SQLRemoveDSNFromIni(tds_dstr_cstr(&di->origdsn))
			    || !SQLWriteDSNToIni(tds_dstr_cstr(&di->dsn), lpszDriver)) {
				goto Fail;
			}
		}
		if (!write_all_strings(di)) {
			goto Fail;
		}
		break;
	case ODBC_REMOVE_DSN:
		if (!SQLRemoveDSNFromIni(tds_dstr_cstr(&di->dsn))) {
			goto Fail;
		}
		break;
	}

	/* Clean up and return TRUE, indicating that the change took place */
	free_dsninfo(di);
	DONESOCKET();
	return TRUE;

      Fail:
	free_dsninfo(di);
	DONESOCKET();
	return FALSE;
}
Пример #8
0
/* {{{ MADB_SaveDSN */
my_bool MADB_SaveDSN(MADB_Dsn *Dsn)
{
  int i= 1;
  char Value[32];
  my_bool ret;
  DWORD ErrNum;

  if (!SQLValidDSN(Dsn->DSNName))
  {
    strcpy_s(Dsn->ErrorMsg, SQL_MAX_MESSAGE_LENGTH, "Invalid Data Source Name");
    return FALSE;
  }

  if (!SQLRemoveDSNFromIni(Dsn->DSNName))
  {
    SQLInstallerError(1,&ErrNum, Dsn->ErrorMsg, SQL_MAX_MESSAGE_LENGTH, NULL);
    return FALSE;
  }
  if (!SQLWriteDSNToIni(Dsn->DSNName, Dsn->Driver))
  {
    SQLInstallerError(1,&ErrNum, Dsn->ErrorMsg, SQL_MAX_MESSAGE_LENGTH, NULL);
    return FALSE;
  }

  while(DsnKeys[i].DsnKey)
  {
    ret= TRUE;
    switch(DsnKeys[i].Type){
    case DSN_TYPE_BOOL:
        ret= SQLWritePrivateProfileString(Dsn->DSNName, DsnKeys[i].DsnKey, 
        *(my_bool *)((char *)Dsn + DsnKeys[i].DsnOffset) ? "1" : "0", "ODBC.INI");
      break;
    case DSN_TYPE_INT:
      {
        my_snprintf(Value ,32, "%d", *(int *)((char *)Dsn + DsnKeys[i].DsnOffset));
        ret= SQLWritePrivateProfileString(Dsn->DSNName, DsnKeys[i].DsnKey, Value, "ODBC.INI");
      }
      break;
    case DSN_TYPE_STRING:
    case DSN_TYPE_COMBO:
      {
        char *Val= *(char **)((char *)Dsn + DsnKeys[i].DsnOffset);
        if (Val && Val[0])
          ret= SQLWritePrivateProfileString(Dsn->DSNName, DsnKeys[i].DsnKey, Val, "ODBC.INI");
      }
      break;
    }
    if (!ret)
    {
      SQLInstallerError(1,&ErrNum, Dsn->ErrorMsg, SQL_MAX_MESSAGE_LENGTH, NULL);
      return FALSE;
    }
    i++;
  }
  /* Save Options */
  my_snprintf(Value ,32, "%d", Dsn->Options);
  if (!(ret= SQLWritePrivateProfileString(Dsn->DSNName, "OPTIONS", Value, "ODBC.INI")))
  {
    SQLInstallerError(1,&ErrNum, Dsn->ErrorMsg, SQL_MAX_MESSAGE_LENGTH, NULL);
    return FALSE;
  }
  return TRUE;
}