Пример #1
0
RETCODE INSTAPI
SQLPostInstallerErrorW (DWORD fErrorCode, LPWSTR szErrorMsg)
{
  char *_errormsg_u8 = NULL;
  RETCODE retcode = SQL_ERROR;

  _errormsg_u8 = (char *) dm_SQL_WtoU8 ((SQLWCHAR *) szErrorMsg, SQL_NTS);
  if (_errormsg_u8 == NULL && szErrorMsg)
    {
      PUSH_ERROR (ODBC_ERROR_OUT_OF_MEM);
      goto done;
    }

  retcode = SQLPostInstallerError (fErrorCode, _errormsg_u8);

done:
  MEM_FREE (_errormsg_u8);

  return retcode;
}
Пример #2
0
/*--------
 *	ConfigDriver
 *
 *	Description:	ODBC Setup entry point
 *			This entry point is called by the ODBC Installer
 *			(see file header for more details)
 *	Arguments :	hwnd ----------- Parent window handle
 *			fRequest ------- Request type (i.e., add, config, or remove)
 *			lpszDriver ----- Driver name
 *			lpszArgs ------- A null-terminated string containing
				arguments for a driver specific fRequest
 *			lpszMsg -------- A null-terimated string containing
				an output message from the driver setup
 *			cnMsgMax ------- Length of lpszMSg
 *			pcbMsgOut ------ Total number of bytes available to
				return in lpszMsg
 *	Returns :	TRUE success, FALSE otherwise
 *--------
 */
BOOL		CALLBACK
ConfigDriver(HWND hwnd,
		WORD fRequest,
		LPCSTR lpszDriver,
		LPCSTR lpszArgs,
		LPSTR lpszMsg,
		WORD cbMsgMax,
		WORD *pcbMsgOut)
{
	DWORD	errorCode = 0;
	BOOL	fSuccess = TRUE;	/* Success/fail flag */

	if (cbMsgMax > 0 && NULL != lpszMsg)
		*lpszMsg = '\0';
	if (NULL != pcbMsgOut)
		*pcbMsgOut = 0;

	/* Add the driver */
	switch (fRequest)
	{
		case ODBC_INSTALL_DRIVER:
			fSuccess = SetDriverAttributes(lpszDriver, &errorCode, lpszMsg, cbMsgMax);
			if (cbMsgMax > 0 && NULL != lpszMsg)
				*pcbMsgOut = (WORD) strlen(lpszMsg);
			break;
		case ODBC_REMOVE_DRIVER:
			break;
		default:
			errorCode = ODBC_ERROR_INVALID_REQUEST_TYPE;
			fSuccess = FALSE;
	}

	if (!fSuccess)
		SQLPostInstallerError(errorCode, lpszMsg);
	return fSuccess;
}
Пример #3
0
my_bool DSNDialog(HWND hwndParent,
                  WORD fRequest,
                  LPCSTR lpszDriver,
                  LPCSTR lpszAttributes,
                  MADB_Dsn *Dsn)
{
  MSG msg;
  BOOL ret;
  char *DsnName= NULL;
  my_bool DsnExists= FALSE;

  if (Dsn->isPrompt < 0 || Dsn->isPrompt > MAODBC_PROMPT_REQUIRED)
  {
    Dsn->isPrompt= MAODBC_CONFIG;
  }

  EffectiveDisabledPages=     DisabledPages[Dsn->isPrompt];
  EffectiveDisabledControls=  DisabledControls[Dsn->isPrompt];

  if (lpszAttributes)
    DsnName= strchr((char *)lpszAttributes, '=');
  
  if (lpszDriver)
    MADB_DriverGet((char *)lpszDriver);

  if (DsnName)
  {
    ++DsnName;
    /* In case of prompting we are supposed to show dialog even DSN name is incorrect */
    if (!Dsn->isPrompt && !SQLValidDSN(DsnName))
    {
      if (hwndParent)
        MessageBox(hwndParent, "Validation of data source name failed", "Error", MB_ICONERROR | MB_OK);
      return FALSE;
    }
  }

  if (!DsnName && Dsn && Dsn->DSNName)
  {
    DsnName= Dsn->DSNName;
  }
  else if (DsnName && Dsn)
  {
    /* Need to free current value in Dsn->DSNName */
    MADB_SUBSTITUTE(Dsn->DSNName, _strdup(DsnName));
  }

  /* Even if DsnName invalid(in case of prompt) - we should not have problem */
  DsnExists= MADB_DSN_Exists(DsnName);
 
  InitCommonControls();

  if (lpszDriver)
    Dsn->Driver= _strdup(lpszDriver);

  SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &Environment);
  SQLSetEnvAttr(Environment, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);

  if (fRequest == ODBC_ADD_DSN)
  {
    if (DsnExists && hwndParent)
    {
      if (MessageBox(hwndParent, "Data source name already exists, do you want to replace it?", 
                      "Question", MB_ICONQUESTION | MB_YESNO) != IDYES)
        return FALSE;
    }
    Dsn->IsTcpIp= 1;
  }
  else
  {
    /* i.e. not a prompt */
    if (Dsn->isPrompt == MAODBC_CONFIG)
    {
      if (!DsnExists)
      {
        MessageBox(0, "Data source name not found", "Error", MB_ICONERROR | MB_OK);
        return FALSE;
      }
      else if (!MADB_ReadDSN(Dsn, (char *)lpszAttributes, TRUE))
      {
        SQLPostInstallerError(ODBC_ERROR_INVALID_DSN, Dsn->ErrorMsg);
        return FALSE;
      }
    }
  }

  notCanceled= TRUE;
  hwndMain= CreateDialogParam(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), 0, DialogProc, 0);
  SetWindowLongPtr(hwndMain, DWLP_USER, (LONG)Dsn);

  /* Setting first not disabled page */
  CurrentPage= -1;
  SetPage(hwndMain, 1);

  Edit_SetReadOnly(GetDlgItem(hwndTab[0], txtDsnName), 
                   (hwndParent && DsnName && fRequest == ODBC_ADD_DSN) ? TRUE : FALSE);

  SetDialogFields();
  CenterWindow(hwndMain);
  ShowWindow(hwndMain, SW_SHOW);

  while((ret = GetMessage(&msg, 0, 0, 0)) != 0) {
    if(ret == -1)
      break;

    if(!IsDialogMessage(hwndTab[CurrentPage], &msg)) {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  }

  SQLFreeHandle(SQL_HANDLE_ENV, Environment);

  return notCanceled;
}
Пример #4
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;
}
Пример #5
0
BOOL
InstallDriverPathLength (WORD * pcbPathOut, LPSTR envname)
{
#ifdef _MAC
  OSErr result;
  long fldrDid;
  short fldrRef;
#endif
  BOOL retcode = FALSE;
  WORD len = 0;
  char path[1024];
  char *ptr;

#if	!defined(UNIX_PWD)
#ifdef _MAC
  result = FindFolder (kOnSystemDisk, kExtensionFolderType, kDontCreateFolder,
      &fldrRef, &fldrDid);
  if (result != noErr)
    {
      PUSH_ERROR (ODBC_ERROR_GENERAL_ERR);
      goto quit;
    }

  ptr = get_full_pathname (fldrDid, fldrRef);
  len = STRLEN (ptr);
  free (ptr);

  goto done;
#else
  /*
   *  On Windows, there is only one place to look
   */
  len = GetWindowsDirectory (path, sizeof (path));
  goto done;
#endif
#else

  /*
   *  1. Check $ODBCDRIVERS environment variable
   */
  if ((ptr = getenv (envname)) && access (ptr, R_OK | W_OK | X_OK) == 0)
    {
      len = STRLEN (ptr);
      goto done;
    }

  /*
   * 2. Check /usr/local/lib and /usr/lib
   */
#ifdef _BE
  if (access ("/boot/beos/system/lib", R_OK | W_OK | X_OK) == 0)
    {
      len = STRLEN ("/boot/beos/system/lib");
      goto done;
    }
#else
  if (access ("/usr/local/lib", R_OK | W_OK | X_OK) == 0)
    {
      len = STRLEN ("/usr/local/lib");
      goto done;
    }
#endif

#ifdef _BE
  if (access ("/boot/home/config/lib", R_OK | W_OK | X_OK) == 0)
    {
      len = STRLEN ("/boot/home/config/lib");
      goto done;
    }
#else
  if (access ("/usr/lib", R_OK | W_OK | X_OK) == 0)
    {
      len = STRLEN ("/usr/lib");
      goto done;
    }
#endif

  /*
   *  3. Check either $HOME
   */
  if (!(ptr = getenv ("HOME")))
    {
      ptr = (char *) getpwuid (getuid ());
      if (ptr)
	ptr = ((struct passwd *) ptr)->pw_dir;
    }

  if (ptr)
    {
#ifdef _BE
      sprintf (path, "%s/config/lib", ptr);
#else
      sprintf (path, "%s/lib", ptr);
#endif
      if (access (path, R_OK | W_OK | X_OK) == 0)
	{
	  len = STRLEN (path);
	  goto done;
	}
    }

  if (!mkdir (path, 0755))
    goto done;

#endif

  SQLPostInstallerError (ODBC_ERROR_GENERAL_ERR,
      "Cannot retrieve a directory where to install the driver or translator.");
  goto quit;

done:
  retcode = TRUE;

quit:
  if (pcbPathOut)
    *pcbPathOut = len;
  return retcode;
}
Пример #6
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;
}
/*
   Add, edit, or remove a Data Source Name (DSN). This function is
   called by "Data Source Administrator" on Windows, or similar
   application on Unix.
*/
BOOL INSTAPI ConfigDSNW(HWND hWnd, WORD nRequest, LPCWSTR pszDriver,
                        LPCWSTR pszAttributes)
{
  DataSource *ds= ds_new();
  BOOL rc= TRUE;
  Driver *driver= NULL;
  SQLWCHAR *origdsn= NULL;

  if (pszAttributes && *pszAttributes)
  {
    SQLWCHAR delim= ';';

#ifdef _WIN32
    /* 
      if there's no ;, then it's most likely null-delimited

     NOTE: the double null-terminated strings are not working
     *      with UnixODBC-GUI-Qt (posted a bug ) 
    */
    if (!sqlwcharchr(pszAttributes, delim))
      delim= 0;
#endif

    if (ds_from_kvpair(ds, pszAttributes, delim))
    {
      SQLPostInstallerError(ODBC_ERROR_INVALID_KEYWORD_VALUE,
                            W_INVALID_ATTR_STR);
      rc= FALSE;
      goto exitConfigDSN;
    }
    if (ds_lookup(ds) && nRequest != ODBC_ADD_DSN)
    {
      /* ds_lookup() will already set SQLInstallerError */
      rc= FALSE;
      goto exitConfigDSN;
    }
    origdsn= sqlwchardup(ds->name, SQL_NTS);
  }

  switch (nRequest)
  {
  case ODBC_ADD_DSN:
    driver= driver_new();
    memcpy(driver->name, pszDriver,
           (sqlwcharlen(pszDriver) + 1) * sizeof(SQLWCHAR));
    if (driver_lookup(driver))
    {
      rc= FALSE;
      break;
    }
    if (hWnd)
    {
      /*
        hWnd means we will at least try to prompt, at which point
        the driver lib will be replaced by the name
      */
      ds_set_strattr(&ds->driver, driver->lib);
    }
    else
    {
      /*
        no hWnd is a likely a call from an app w/no prompting so
        we put the driver name immediately
      */
      ds_set_strattr(&ds->driver, driver->name);
    }
  case ODBC_CONFIG_DSN:
#ifdef _WIN32
    /*
      for windows, if hWnd is NULL, we try to add the dsn
      with what information was given
    */
    if (!hWnd || ShowOdbcParamsDialog(ds, hWnd, FALSE) == 1)
#else
    if (ShowOdbcParamsDialog(ds, hWnd, FALSE) == 1)
#endif
    {
      /* save datasource */
      if (ds_add(ds))
        rc= FALSE;
      /* if the name is changed, remove the old dsn */
      if (origdsn && memcmp(origdsn, ds->name,
                            (sqlwcharlen(origdsn) + 1) * sizeof(SQLWCHAR)))
        SQLRemoveDSNFromIni(origdsn);
    }
    break;
  case ODBC_REMOVE_DSN:
    if (SQLRemoveDSNFromIni(ds->name) != TRUE)
      rc= FALSE;
    break;
  }

exitConfigDSN:
  x_free(origdsn);
  ds_delete(ds);
  if (driver)
    driver_delete(driver);
  return rc;
}
Пример #8
0
BOOL INSTAPI
ConfigDriver (
    HWND	  hwndParent,
    WORD	  fRequest,
    LPCSTR	  lpszDriver,
    LPCSTR	  lpszArgs,
    LPSTR	  lpszMsg,
    WORD	  cbMsgMax,
    WORD	* pcbMsgOut)
{
  char *curr, *cour;
  char driverread[4096] = { 0 };
  BOOL retcode = FALSE;
  UWORD confMode = ODBC_USER_DSN;

  /* Map the request User/System */
  if (fRequest < ODBC_INSTALL_DRIVER || fRequest > ODBC_CONFIG_DRIVER_MAX)
    {
      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);

  /* Treat corresponding to the request */
  switch (fRequest)
    {
    case ODBC_INSTALL_DRIVER:
      /* Check if the DRIVER with this name already exists */
      SQLSetConfigMode (confMode);
#ifdef WIN32
      if (hwndParent
	  && SQLGetPrivateProfileString ("ODBC 32 bit Drivers", lpszDriver,
	      "", driverread, sizeof (driverread), "odbcinst.ini")
	  && !create_confirm (hwndParent, NULL,
	      "Are you sure you want to overwrite this driver ?"))
#else
#  ifdef _MACX
      if (hwndParent
	  && SQLGetPrivateProfileString ("ODBC Drivers", lpszDriver, "",
	      driverread, sizeof (driverread), "odbcinst.ini")
	  && !create_confirm (hwndParent, NULL,
	      "Are you sure you want to overwrite this driver ?"))
#  else
      if (hwndParent
	  && SQLGetPrivateProfileString ("ODBC Drivers", lpszDriver, "",
	      driverread, sizeof (driverread), "odbcinst.ini")
	  && !create_confirm (hwndParent, NULL,
	      "Are you sure you want to overwrite this driver ?"))
#  endif
#endif
	{
	  SQLPostInstallerError (ODBC_ERROR_DRIVER_SPECIFIC,
	      "Driver already installed previously.");
	  goto done;
	}

      /* Add the Driver to the ODBC Drivers */
      SQLSetConfigMode (confMode);
      if (!SQLInstallDriverEx (lpszArgs, NULL, driverread,
	      sizeof (driverread), NULL, ODBC_INSTALL_COMPLETE, NULL))
	{
	  SQLPostInstallerError (ODBC_ERROR_DRIVER_SPECIFIC,
	      "Could not add the driver information.");
	  goto done;
	}

      break;

    case ODBC_CONFIG_DRIVER:
      if (!lpszArgs || !STRLEN (lpszArgs))
	{
	  SQLPostInstallerError (ODBC_ERROR_DRIVER_SPECIFIC,
	      "No enough parameters for configururation.");
	  goto done;
	}

      /* Add each keyword and values */
      for (curr = (LPSTR) lpszArgs; *curr; curr += (STRLEN (curr) + 1))
	{
	  STRCPY (driverread, curr);
	  cour = strchr (driverread, '=');
	  if (cour)
	    *cour = 0;
	  SQLSetConfigMode (confMode);
	  if (!SQLWritePrivateProfileString (lpszDriver, driverread, (cour
		      && STRLEN (cour + 1)) ? cour + 1 : NULL,
		  "odbcinst.ini"))
	    goto done;
	}
      break;

    case ODBC_REMOVE_DRIVER:
      /* Remove the Driver to the ODBC Drivers */
      SQLSetConfigMode (confMode);
      if (!SQLRemoveDriver (lpszDriver, TRUE, NULL))
	{
	  SQLPostInstallerError (ODBC_ERROR_DRIVER_SPECIFIC,
	      "Could not remove driver information.");
	  goto done;
	}
      break;

    default:
      SQLPostInstallerError (ODBC_ERROR_REQUEST_FAILED, NULL);
      goto done;
    };

quit:
  retcode = TRUE;

done:
  if (pcbMsgOut)
    *pcbMsgOut = 0;
  return retcode;
}