From: Hans Leidekker <hans@codeweavers.com> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=59799 --- dlls/odbc32/proxyodbc.c | 53 ++++++++++++++++++++++++++++++++++---- dlls/odbc32/tests/odbc32.c | 17 +++++++++--- dlls/odbc32/unixlib.h | 10 +++++++ 3 files changed, 72 insertions(+), 8 deletions(-) diff --git a/dlls/odbc32/proxyodbc.c b/dlls/odbc32/proxyodbc.c index 2ced00dc3fd..dcd38eb1066 100644 --- a/dlls/odbc32/proxyodbc.c +++ b/dlls/odbc32/proxyodbc.c @@ -1591,7 +1591,7 @@ static SQLRETURN alloc_con_handle( struct connection *con ) static SQLRETURN create_con( struct connection *con ) { WCHAR odbc_ver[6]; - SQLSMALLINT len; + SQLSMALLINT len, i; SQLRETURN ret; if ((ret = alloc_con_handle( con ))) return ret; @@ -1603,6 +1603,10 @@ static SQLRETURN create_con( struct connection *con ) set_con_attr( con, SQL_ATTR_LOGIN_TIMEOUT, INT_PTR(con->attr_login_timeout), 0 )) WARN( "failed to set login timeout\n" ); + for (i = 0; i < con->driver_attr_count; i++) + if ((ret = set_con_attr( con, con->driver_attr[i].id, con->driver_attr[i].value, con->driver_attr[i].len ))) + WARN( "failed to set driver attribute %u error %u\n", con->driver_attr[i].id, ret ); + if (con->hdr.win32_handle) { ret = get_info_win32_w( con, SQL_DRIVER_ODBC_VER, odbc_ver, sizeof(odbc_ver), &len ); @@ -2470,6 +2474,7 @@ static void cleanup_object( struct object *obj ) case SQL_HANDLE_ENV: { struct environment *env = (struct environment *)obj; + RegCloseKey( env->drivers_key ); RegCloseKey( env->sources_key ); env->drivers_key = env->sources_key = NULL; @@ -2479,6 +2484,12 @@ static void cleanup_object( struct object *obj ) case SQL_HANDLE_DBC: { struct connection *con = (struct connection *)obj; + UINT32 i; + + for (i = 0; i < con->driver_attr_count; i++) free( con->driver_attr[i].value ); + free( con->driver_attr ); + con->driver_attr = NULL; + con->driver_attr_count = 0; release_env( con->env ); con->env = NULL; break; @@ -2486,6 +2497,7 @@ static void cleanup_object( struct object *obj ) case SQL_HANDLE_STMT: { struct statement *stmt = (struct statement *)obj; + free_col_bindings( stmt ); free_param_bindings( stmt ); free_descriptors( stmt ); @@ -3877,6 +3889,27 @@ static SQLRETURN set_connect_attr_win32_a( struct connection *con, SQLINTEGER at return ret; } +#ifndef SQL_CONNECT_OPT_DRVR_START +#define SQL_CONNECT_OPT_DRVR_START 1000 +#endif + +static SQLRETURN store_driver_attribute( struct connection *con, SQLINTEGER id, SQLPOINTER value, SQLINTEGER len ) +{ + struct driver_attribute *tmp, *attr; + + if (!(tmp = realloc( con->driver_attr, (con->driver_attr_count + 1) * sizeof(*attr) ))) return SQL_ERROR; + con->driver_attr = tmp; + + attr = &con->driver_attr[con->driver_attr_count]; + attr->id = id; + if (!(attr->value = malloc( len ))) return SQL_ERROR; + memcpy( attr->value, value, len ); + attr->len = len; + + con->driver_attr_count++; + return SQL_SUCCESS; +} + /************************************************************************* * SQLSetConnectAttr [ODBC32.039] */ @@ -3914,8 +3947,13 @@ SQLRETURN WINAPI SQLSetConnectAttr(SQLHDBC ConnectionHandle, SQLINTEGER Attribut break; default: - FIXME( "unhandled attribute %d\n", Attribute ); - ret = SQL_ERROR; + if (Attribute >= SQL_CONNECT_OPT_DRVR_START) + ret = store_driver_attribute( con, Attribute, Value, StringLength ); + else + { + FIXME( "unhandled attribute %d\n", Attribute ); + ret = SQL_ERROR; + } break; } } @@ -7272,8 +7310,13 @@ SQLRETURN WINAPI SQLSetConnectAttrW(SQLHDBC ConnectionHandle, SQLINTEGER Attribu break; default: - FIXME( "unhandled attribute %d\n", Attribute ); - ret = SQL_ERROR; + if (Attribute >= SQL_CONNECT_OPT_DRVR_START) + ret = store_driver_attribute( con, Attribute, Value, StringLength ); + else + { + FIXME( "unhandled attribute %d\n", Attribute ); + ret = SQL_ERROR; + } break; } } diff --git a/dlls/odbc32/tests/odbc32.c b/dlls/odbc32/tests/odbc32.c index b83e6ebfdc3..733222f128f 100644 --- a/dlls/odbc32/tests/odbc32.c +++ b/dlls/odbc32/tests/odbc32.c @@ -73,6 +73,7 @@ DEFINE_EXPECT( driver_SQLGetInfo ); DEFINE_EXPECT( driver_SQLGetInfo_SQL_DRIVER_ODBC_VER ); DEFINE_EXPECT( driver_SQLConnect ); DEFINE_EXPECT( driver_SQLGetConnectAttr ); +DEFINE_EXPECT( driver_SQLSetConnectAttr ); DEFINE_EXPECT( driver_SQLDisconnect ); DEFINE_EXPECT( driver_SQLDriverConnect ); DEFINE_EXPECT( driver_SQLBrowseConnect ); @@ -176,8 +177,12 @@ static SQLRETURN WINAPI driver_SQLGetConnectAttr( SQLHDBC con, SQLINTEGER attr, static SQLRETURN WINAPI driver_SQLSetConnectAttr( SQLHDBC con, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER len ) { - ok( 0, "unexpected call\n" ); - return SQL_ERROR; + CHECK_EXPECT( driver_SQLSetConnectAttr ); + ok( attr == 1000, "attr = %d\n", attr ); + ok( val != NULL, "val = %p\n", val ); + ok( *(SQLUINTEGER *)val == 0xdeadbeef, "*val = %u\n", *(SQLUINTEGER *)val ); + ok( len == sizeof(SQLUINTEGER), "len = %d\n", len ); + return SQL_SUCCESS; } static SQLRETURN WINAPI driver_SQLGetInfo( SQLHDBC con, SQLUSMALLINT type, @@ -730,7 +735,7 @@ static void test_SQLConnect( void ) SQLHDBC con; SQLRETURN ret; SQLINTEGER size, version, pooling; - SQLUINTEGER timeout; + SQLUINTEGER timeout, driver_attr; SQLSMALLINT len; char str[32]; @@ -776,6 +781,10 @@ static void test_SQLConnect( void ) ok( ret == SQL_SUCCESS, "got %d\n", ret ); ok( timeout == SQL_LOGIN_TIMEOUT_DEFAULT, "wrong timeout %d\n", timeout ); + driver_attr = 0xdeadbeef; + ret = SQLSetConnectAttr( con, 1000, &driver_attr, sizeof(driver_attr) ); + ok( ret == SQL_SUCCESS, "got %d\n", ret ); + SET_EXPECT( driver_SQLAllocHandle_env ); SET_EXPECT( driver_SQLSetEnvAttr ); SET_EXPECT( driver_SQLAllocHandle_con ); @@ -783,6 +792,7 @@ static void test_SQLConnect( void ) SET_EXPECT( driver_SQLConnect ); SET_EXPECT( driver_SQLGetDiagRec ); SET_EXPECT( driver_SQLGetInfo ); + SET_EXPECT( driver_SQLSetConnectAttr ); ret = SQLConnect( con, (SQLCHAR *)"winetest_dsn", SQL_NTS, (SQLCHAR *)"winetest", SQL_NTS, (SQLCHAR *)"winetest", SQL_NTS ); CHECK_CALLED( driver_SQLAllocHandle_env ); @@ -790,6 +800,7 @@ static void test_SQLConnect( void ) CHECK_CALLED( driver_SQLAllocHandle_con ); CHECK_CALLED( driver_SQLGetInfo_SQL_DRIVER_ODBC_VER ); CHECK_CALLED( driver_SQLConnect ); + CHECK_CALLED( driver_SQLSetConnectAttr); todo_wine CHECK_CALLED( driver_SQLGetDiagRec ); todo_wine CHECK_CALLED( driver_SQLGetInfo ); ok (ret == SQL_SUCCESS, "got %d\n", ret ); diff --git a/dlls/odbc32/unixlib.h b/dlls/odbc32/unixlib.h index 48e34084274..5a458e6f58a 100644 --- a/dlls/odbc32/unixlib.h +++ b/dlls/odbc32/unixlib.h @@ -217,6 +217,13 @@ struct environment BOOL sources_system; }; +struct driver_attribute +{ + UINT32 id; + void *value; + UINT32 len; +}; + struct connection { struct object hdr; @@ -228,6 +235,9 @@ struct connection UINT32 attr_con_timeout; BOOL login_timeout_set; UINT32 attr_login_timeout; + /* driver attributes */ + struct driver_attribute *driver_attr; + UINT32 driver_attr_count; }; struct statement -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11024