RETCODE SQL_API PGAPI_DriverConnect( HDBC hdbc, HWND hwnd, const SQLCHAR FAR * szConnStrIn, SQLSMALLINT cbConnStrIn, SQLCHAR FAR * szConnStrOut, SQLSMALLINT cbConnStrOutMax, SQLSMALLINT FAR * pcbConnStrOut, SQLUSMALLINT fDriverCompletion) { CSTR func = "PGAPI_DriverConnect"; ConnectionClass *conn = (ConnectionClass *) hdbc; ConnInfo *ci; #ifdef WIN32 RETCODE dialog_result; #endif BOOL paramRequired, didUI = FALSE; RETCODE result; char *connStrIn = NULL; char connStrOut[MAX_CONNECT_STRING]; int retval; char salt[5]; char password_required = AUTH_REQ_OK; ssize_t len = 0; SQLSMALLINT lenStrout; mylog("%s: entering...\n", func); if (!conn) { CC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } connStrIn = make_string(szConnStrIn, cbConnStrIn, NULL, 0); #ifdef FORCE_PASSWORD_DISPLAY mylog("**** PGAPI_DriverConnect: fDriverCompletion=%d, connStrIn='%s'\n", fDriverCompletion, connStrIn); qlog("conn=%p, PGAPI_DriverConnect( in)='%s', fDriverCompletion=%d\n", conn, connStrIn, fDriverCompletion); #else if (get_qlog() || get_mylog()) { char *hide_str = hide_password(connStrIn); mylog("**** PGAPI_DriverConnect: fDriverCompletion=%d, connStrIn='%s'\n", fDriverCompletion, NULL_IF_NULL(hide_str)); qlog("conn=%p, PGAPI_DriverConnect( in)='%s', fDriverCompletion=%d\n", conn, NULL_IF_NULL(hide_str), fDriverCompletion); if (hide_str) free(hide_str); } #endif /* FORCE_PASSWORD_DISPLAY */ ci = &(conn->connInfo); /* Parse the connect string and fill in conninfo for this hdbc. */ dconn_get_connect_attributes(connStrIn, ci); /* * If the ConnInfo in the hdbc is missing anything, this function will * fill them in from the registry (assuming of course there is a DSN * given -- if not, it does nothing!) */ getDSNinfo(ci, CONN_DONT_OVERWRITE); dconn_get_common_attributes(connStrIn, ci); logs_on_off(1, ci->drivers.debug, ci->drivers.commlog); if (connStrIn) { free(connStrIn); connStrIn = NULL; } /* Fill in any default parameters if they are not there. */ getDSNdefaults(ci); /* initialize pg_version */ CC_initialize_pg_version(conn); memset(salt, 0, sizeof(salt)); #ifdef WIN32 dialog: #endif ci->focus_password = password_required; inolog("DriverCompletion=%d\n", fDriverCompletion); switch (fDriverCompletion) { #ifdef WIN32 case SQL_DRIVER_PROMPT: dialog_result = dconn_DoDialog(hwnd, ci); didUI = TRUE; if (dialog_result != SQL_SUCCESS) return dialog_result; break; case SQL_DRIVER_COMPLETE_REQUIRED: /* Fall through */ case SQL_DRIVER_COMPLETE: paramRequired = password_required; /* Password is not a required parameter. */ if (ci->database[0] == '\0') paramRequired = TRUE; else if (ci->port[0] == '\0') paramRequired = TRUE; #ifdef WIN32 else if (ci->server[0] == '\0') paramRequired = TRUE; #endif /* WIN32 */ if (paramRequired) { dialog_result = dconn_DoDialog(hwnd, ci); didUI = TRUE; if (dialog_result != SQL_SUCCESS) return dialog_result; } break; #else case SQL_DRIVER_PROMPT: case SQL_DRIVER_COMPLETE: case SQL_DRIVER_COMPLETE_REQUIRED: #endif case SQL_DRIVER_NOPROMPT: break; } /* * Password is not a required parameter unless authentication asks for * it. For now, I think it's better to just let the application ask * over and over until a password is entered (the user can always hit * Cancel to get out) */ paramRequired = FALSE; if (ci->database[0] == '\0') paramRequired = TRUE; else if (ci->port[0] == '\0') paramRequired = TRUE; #ifdef WIN32 else if (ci->server[0] == '\0') paramRequired = TRUE; #endif /* WIN32 */ if (paramRequired) { if (didUI) return SQL_NO_DATA_FOUND; CC_set_error(conn, CONN_OPENDB_ERROR, "connction string lacks some options", func); return SQL_ERROR; } inolog("before CC_connect\n"); /* do the actual connect */ retval = CC_connect(conn, password_required, salt); if (retval < 0) { /* need a password */ if (fDriverCompletion == SQL_DRIVER_NOPROMPT) { CC_log_error(func, "Need password but Driver_NoPrompt", conn); return SQL_ERROR; /* need a password but not allowed to * prompt so error */ } else { #ifdef WIN32 password_required = -retval; goto dialog; #else return SQL_ERROR; /* until a better solution is found. */ #endif } } else if (retval == 0) { /* error msg filled in above */ CC_log_error(func, "Error from CC_Connect", conn); return SQL_ERROR; } /* * Create the Output Connection String */ result = SQL_SUCCESS; lenStrout = cbConnStrOutMax; if (conn->ms_jet && lenStrout > 255) lenStrout = 255; makeConnectString(connStrOut, ci, lenStrout); len = strlen(connStrOut); if (szConnStrOut) { /* * Return the completed string to the caller. The correct method * is to only construct the connect string if a dialog was put up, * otherwise, it should just copy the connection input string to * the output. However, it seems ok to just always construct an * output string. There are possible bad side effects on working * applications (Access) by implementing the correct behavior, * anyway. */ /*strncpy_null(szConnStrOut, connStrOut, cbConnStrOutMax);*/ strncpy(szConnStrOut, connStrOut, cbConnStrOutMax); if (len >= cbConnStrOutMax) { int clen; for (clen = cbConnStrOutMax - 1; clen >= 0 && szConnStrOut[clen] != ';'; clen--) szConnStrOut[clen] = '\0'; result = SQL_SUCCESS_WITH_INFO; CC_set_error(conn, CONN_TRUNCATED, "The buffer was too small for the ConnStrOut.", func); } } if (pcbConnStrOut) *pcbConnStrOut = (SQLSMALLINT) len; #ifdef FORCE_PASSWORD_DISPLAY if (cbConnStrOutMax > 0) { mylog("szConnStrOut = '%s' len=%d,%d\n", NULL_IF_NULL(szConnStrOut), len, cbConnStrOutMax); qlog("conn=%p, PGAPI_DriverConnect(out)='%s'\n", conn, NULL_IF_NULL(szConnStrOut)); } #else if (get_qlog() || get_mylog()) { char *hide_str = NULL; if (cbConnStrOutMax > 0) hide_str = hide_password(szConnStrOut); mylog("szConnStrOut = '%s' len=%d,%d\n", NULL_IF_NULL(hide_str), len, cbConnStrOutMax); qlog("conn=%p, PGAPI_DriverConnect(out)='%s'\n", conn, NULL_IF_NULL(hide_str)); if (hide_str) free(hide_str); } #endif /* FORCE_PASSWORD_DISPLAY */ if (connStrIn) free(connStrIn); mylog("PGAPI_DriverConnect: returning %d\n", result); return result; }
void test_connection(HANDLE hwnd, ConnInfo *ci, BOOL withDTC) { int errnum; char out_conn[MAX_CONNECT_STRING_LEN]; SQLRETURN ret; SQLHENV env = SQL_NULL_HANDLE; SQLHDBC conn = SQL_NULL_HANDLE; SQLSMALLINT str_len; char dsn_1st; BOOL connected = FALSE; #ifdef UNICODE_SUPPORT SQLWCHAR wout_conn[MAX_CONNECT_STRING_LEN]; SQLWCHAR szMsg[SQL_MAX_MESSAGE_LENGTH]; const SQLWCHAR *ermsg = NULL; SQLWCHAR *conn_str; #else SQLCHAR szMsg[SQL_MAX_MESSAGE_LENGTH]; const SQLCHAR *ermsg = NULL; SQLCHAR *conn_str; #endif /* UNICODE_SUPPORT */ dsn_1st = ci->dsn[0]; ci->dsn[0] = '\0'; makeConnectString(out_conn, ci, sizeof(out_conn)); mylog("conn_string=%s\n", out_conn); #ifdef UNICODE_SUPPORT msgtowstr(out_conn, wout_conn, _countof(wout_conn)); conn_str = wout_conn; #else conn_str = out_conn; #endif /* UNICODE_SUPPORT */ ci->dsn[0] = dsn_1st; if (!SQL_SUCCEEDED(ret = SQLALLOCHANDLEFUNC(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env))) { ermsg = _T("SQLAllocHandle for env error"); goto cleanup; } if (!SQL_SUCCEEDED(ret = SQLSETENVATTRFUNC(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, 0))) { snprintf(szMsg, _countof(szMsg), _T("SQLAllocHandle for env error=%d"), ret); goto cleanup; } if (!SQL_SUCCEEDED(ret = SQLALLOCHANDLEFUNC(SQL_HANDLE_DBC, env, &conn))) { SQLGETDIAGRECFUNC(SQL_HANDLE_ENV, env, 1, NULL, &errnum, szMsg, _countof(szMsg), &str_len); ermsg = szMsg; goto cleanup; } if (!SQL_SUCCEEDED(ret = SQLDRIVERCONNECTFUNC(conn, hwnd, conn_str, SQL_NTS, NULL, MAX_CONNECT_STRING_LEN, &str_len, SQL_DRIVER_NOPROMPT))) { SQLGETDIAGRECFUNC(SQL_HANDLE_DBC, conn, 1, NULL, &errnum, szMsg, _countof(szMsg), &str_len); ermsg = szMsg; goto cleanup; } connected = TRUE; ermsg = _T("Connection successful"); if (withDTC) { #ifdef _HANDLE_ENLIST_IN_DTC_ HRESULT res; void *pObj = NULL; pObj = CALL_GetTransactionObject(&res); if (NULL != pObj) { SQLRETURN ret = SQLSETCONNECTATTRFUNC(conn, SQL_ATTR_ENLIST_IN_DTC, (SQLPOINTER) pObj, 0); if (SQL_SUCCEEDED(ret)) { SQLSETCONNECTATTRFUNC(conn, SQL_ATTR_ENLIST_IN_DTC, SQL_DTC_DONE, 0); snprintf(szMsg, _countof(szMsg), _T("%s\nenlistment was successful\n"), ermsg); ermsg = szMsg; } else { SQLGETDIAGRECFUNC(SQL_HANDLE_DBC, conn, 1, NULL, &errnum, szMsg, _countof(szMsg), &str_len); if (szMsg[0] != 0) { snprintf(szMsg, _countof(szMsg), _T("%s\nMSDTC error:%s"), ermsg, szMsg); ermsg = szMsg; } } CALL_ReleaseTransactionObject(pObj); } else if (FAILED(res)) { snprintf(szMsg, _countof(szMsg), _T("%s\nDistibuted Transaction enlistment error %x"), ermsg, res); ermsg = szMsg; } #else /* _HANDLE_ENLIST_IN_DTC_ */ snprintf(szMsg, _countof(szMsg), _T("%s\nDistibuted Transaction enlistment not supported by this driver"), ermsg); ermsg = szMsg; #endif } cleanup: if (NULL != ermsg && NULL != hwnd) { MESSAGEBOXFUNC(hwnd, ermsg, _T("Connection Test"), MB_ICONEXCLAMATION | MB_OK); } #undef _T #undef snprintf #define snprintf _snprintf if (NULL != conn) { if (connected) SQLDISCONNECTFUNC(conn); SQLFREEHANDLEFUNC(SQL_HANDLE_DBC, conn); } if (env) SQLFREEHANDLEFUNC(SQL_HANDLE_ENV, env); return; }