From: Hans Leidekker hans@codeweavers.com
--- dlls/odbc32/proxyodbc.c | 241 +++++++++++++++++++++++++++---------- dlls/odbc32/tests/odbc32.c | 26 +++- 2 files changed, 200 insertions(+), 67 deletions(-)
diff --git a/dlls/odbc32/proxyodbc.c b/dlls/odbc32/proxyodbc.c index 299f1f8e08b..7388cfb3d9c 100644 --- a/dlls/odbc32/proxyodbc.c +++ b/dlls/odbc32/proxyodbc.c @@ -4173,55 +4173,133 @@ SQLRETURN WINAPI SQLTransact(SQLHENV EnvironmentHandle, SQLHDBC ConnectionHandle return ret; }
-static WCHAR *get_datasource( const WCHAR *connection_string ) +struct attribute { - const WCHAR *p = connection_string, *q; - WCHAR *ret = NULL; - unsigned int len; + WCHAR *name; + WCHAR *value; +}; + +struct attribute_list +{ + UINT32 count; + struct attribute **attrs; +}; + +static void free_attribute( struct attribute *attr ) +{ + free( attr->name ); + free( attr->value ); + free( attr ); +} + +static void free_attribute_list( struct attribute_list *list ) +{ + UINT32 i; + for (i = 0; i < list->count; i++) free_attribute( list->attrs[i] ); +} + +static BOOL append_attribute( struct attribute_list *list, struct attribute *attr ) +{ + struct attribute **tmp; + UINT32 new_count = list->count + 1; + + if (!(tmp = realloc( list->attrs, new_count * sizeof(*list->attrs) ))) + return FALSE; + + tmp[list->count] = attr; + list->attrs = tmp; + list->count = new_count; + return TRUE; +}
- if (!p) return NULL; - while (*p) +static SQLRETURN parse_connect_string( struct attribute_list *list, const WCHAR *str ) +{ + const WCHAR *p = str, *q; + struct attribute *attr; + int len; + + list->count = 0; + list->attrs = NULL; + for (;;) { - if (!wcsnicmp( p, L"DSN=", 4 )) + if (!*p) break; + if (!(q = wcschr( p, '=' )) || q == p) return SQL_SUCCESS; + len = q - p; + + if (!(attr = calloc( 1, sizeof(*attr) ))) return SQL_ERROR; + if (!(attr->name = malloc( (len + 1) * sizeof(WCHAR) ))) { - p += 4; - q = wcschr( p, ';' ); - len = q ? (q - p) : wcslen( p ); - if ((ret = malloc( (len + 1) * sizeof(WCHAR) ))) - { - memcpy( ret, p, len * sizeof(WCHAR) ); - ret[len] = 0; - break; - } + free_attribute( attr ); + free_attribute_list( list ); + return SQL_ERROR; + } + memcpy( attr->name, p, len * sizeof(WCHAR) ); + attr->name[len] = 0; + + q++; /* skip = */ + p = wcschr( q, ';' ); + if (p) + { + len = p - q; + p++; + } + else + { + len = wcslen( q ); + p = q + len; + } + + if (!(attr->value = malloc( (len + 1) * sizeof(WCHAR) ))) + { + free_attribute( attr ); + free_attribute_list( list ); + return SQL_ERROR; + } + memcpy( attr->value, q, len * sizeof(WCHAR) ); + attr->value[len] = 0; + + if (!append_attribute( list, attr )) + { + free_attribute( attr ); + free_attribute_list( list ); + return SQL_ERROR; } - p++; } - return ret; + + return SQL_SUCCESS; +} + +static const WCHAR *get_datasource( const struct attribute_list *list ) +{ + UINT32 i; + for (i = 0; i < list->count; i++) if (!wcscmp( list->attrs[i]->name, L"DSN" )) return list->attrs[i]->value; + return NULL; }
-static WCHAR *get_drivername( const WCHAR *connection_string ) +static WCHAR *get_drivername( const struct attribute_list *list ) { - const WCHAR *p = connection_string, *q; - WCHAR *ret = NULL; - unsigned int len; + UINT32 i; + for (i = 0; i < list->count; i++) if (!wcscmp( list->attrs[i]->name, L"DRIVER" )) return list->attrs[i]->value; + return NULL; +} + +static WCHAR *build_connect_string( struct attribute_list *list ) +{ + WCHAR *ret, *ptr; + UINT32 i, len = 0;
- if (!p) return NULL; - while (*p) + for (i = 0; i < list->count; i++) len += wcslen( list->attrs[i]->name ) + wcslen( list->attrs[i]->value ) + 2; + if (!(ptr = ret = malloc( len * sizeof(WCHAR) ))) return NULL; + for (i = 0; i < list->count; i++) { - if (!wcsnicmp( p, L"DRIVER=", 7 )) - { - p += 7; - q = wcschr( p, ';' ); - len = q ? (q - p) : wcslen( p ); - if ((ret = malloc( (len + 1) * sizeof(WCHAR) ))) - { - memcpy( ret, p, len * sizeof(WCHAR) ); - ret[len] = 0; - break; - } - } - p++; + wcscpy( ptr, list->attrs[i]->name ); + ptr += wcslen( ptr ); + *ptr++ = '='; + wcscpy( ptr, list->attrs[i]->value ); + ptr += wcslen( ptr ); + if (i < list->count - 1) *ptr++ = ';'; } + *ptr = 0; return ret; }
@@ -4259,6 +4337,16 @@ static SQLRETURN browse_connect_unix_a( struct connection *con, SQLCHAR *in_conn return ODBC_CALL( SQLBrowseConnect, ¶ms ); }
+static char *strdupWA( const WCHAR *src ) +{ + int len; + char *dst; + if (!src) return NULL; + len = WideCharToMultiByte( CP_ACP, 0, src, -1, NULL, 0, NULL, NULL ); + if ((dst = malloc( len ))) WideCharToMultiByte( CP_ACP, 0, src, -1, dst, len, NULL, NULL ); + return dst; +} + /************************************************************************* * SQLBrowseConnect [ODBC32.055] */ @@ -4266,8 +4354,10 @@ SQLRETURN WINAPI SQLBrowseConnect(SQLHDBC ConnectionHandle, SQLCHAR *InConnectio SQLCHAR *OutConnectionString, SQLSMALLINT BufferLength, SQLSMALLINT *StringLength2) { struct connection *con = (struct connection *)lock_object( ConnectionHandle, SQL_HANDLE_DBC ); - WCHAR *datasource = NULL, *drivername = NULL, *filename = NULL; - WCHAR *connection_string = strdupAW( (const char *)InConnectionString ); + const WCHAR *datasource, *drivername = NULL; + WCHAR *filename = NULL, *connect_string = NULL, *strW = strdupAW( (const char *)InConnectionString ); + SQLCHAR *strA = NULL; + struct attribute_list attrs; SQLRETURN ret = SQL_ERROR;
TRACE("(ConnectionHandle %p, InConnectionString %s, StringLength1 %d, OutConnectionString %p, BufferLength, %d, " @@ -4276,7 +4366,10 @@ SQLRETURN WINAPI SQLBrowseConnect(SQLHDBC ConnectionHandle, SQLCHAR *InConnectio
if (!con) return SQL_INVALID_HANDLE;
- if (!(datasource = get_datasource( connection_string )) && !(drivername = get_drivername( connection_string ))) + if (parse_connect_string( &attrs, strW ) || !(connect_string = build_connect_string( &attrs )) || + !(strA = (SQLCHAR *)strdupWA( connect_string ))) goto done; + + if (!(datasource = get_datasource( &attrs )) && !(drivername = get_drivername( &attrs ))) { WARN( "can't find data source or driver name\n" ); goto done; @@ -4300,8 +4393,7 @@ SQLRETURN WINAPI SQLBrowseConnect(SQLHDBC ConnectionHandle, SQLCHAR *InConnectio if (!SUCCESS((ret = create_env( (struct environment *)con->hdr.parent, FALSE )))) goto done; if (!SUCCESS((ret = create_con( con )))) goto done;
- ret = browse_connect_win32_a( con, InConnectionString, StringLength1, OutConnectionString, - BufferLength, StringLength2 ); + ret = browse_connect_win32_a( con, strA, StringLength1, OutConnectionString, BufferLength, StringLength2 ); } else { @@ -4310,15 +4402,15 @@ SQLRETURN WINAPI SQLBrowseConnect(SQLHDBC ConnectionHandle, SQLCHAR *InConnectio if (!SUCCESS((ret = create_env( (struct environment *)con->hdr.parent, TRUE )))) goto done; if (!SUCCESS((ret = create_con( con )))) goto done;
- ret = browse_connect_unix_a( con, InConnectionString, StringLength1, OutConnectionString, - BufferLength, StringLength2 ); + ret = browse_connect_unix_a( con, strA, StringLength1, OutConnectionString, BufferLength, StringLength2 ); }
done: - free( connection_string ); + free( strA ); + free( strW ); + free( connect_string ); + free_attribute_list( &attrs ); free( filename ); - free( datasource ); - free( drivername );
TRACE("Returning %d\n", ret); unlock_object( &con->hdr ); @@ -5385,8 +5477,10 @@ SQLRETURN WINAPI SQLDriverConnect(SQLHDBC ConnectionHandle, SQLHWND WindowHandle SQLSMALLINT *Length2, SQLUSMALLINT DriverCompletion) { struct connection *con = (struct connection *)lock_object( ConnectionHandle, SQL_HANDLE_DBC ); - WCHAR *datasource = NULL, *drivername = NULL, *filename = NULL; - WCHAR *connection_string = strdupAW( (const char *)InConnectionString ); + const WCHAR *datasource, *drivername = NULL; + WCHAR *filename = NULL, *connect_string = NULL, *strW = strdupAW( (const char *)InConnectionString ); + SQLCHAR *strA = NULL; + struct attribute_list attrs; SQLRETURN ret = SQL_ERROR;
TRACE("(ConnectionHandle %p, WindowHandle %p, InConnectionString %s, Length %d, OutConnectionString %p," @@ -5396,7 +5490,10 @@ SQLRETURN WINAPI SQLDriverConnect(SQLHDBC ConnectionHandle, SQLHWND WindowHandle
if (!con) return SQL_INVALID_HANDLE;
- if (!(datasource = get_datasource( connection_string )) && !(drivername = get_drivername( connection_string ))) + if (parse_connect_string( &attrs, strW ) || !(connect_string = build_connect_string( &attrs )) || + !(strA = (SQLCHAR *)strdupWA( connect_string ))) goto done; + + if (!(datasource = get_datasource( &attrs )) && !(drivername = get_drivername( &attrs ))) { WARN( "can't find data source or driver name\n" ); goto done; @@ -5420,8 +5517,8 @@ SQLRETURN WINAPI SQLDriverConnect(SQLHDBC ConnectionHandle, SQLHWND WindowHandle if (!SUCCESS((ret = create_env( (struct environment *)con->hdr.parent, FALSE )))) goto done; if (!SUCCESS((ret = create_con( con )))) goto done;
- ret = driver_connect_win32_a( con, WindowHandle, InConnectionString, Length, OutConnectionString, - BufferLength, Length2, DriverCompletion ); + ret = driver_connect_win32_a( con, WindowHandle, strA, Length, OutConnectionString, BufferLength, Length2, + DriverCompletion ); } else { @@ -5430,14 +5527,16 @@ SQLRETURN WINAPI SQLDriverConnect(SQLHDBC ConnectionHandle, SQLHWND WindowHandle if (!SUCCESS((ret = create_env( (struct environment *)con->hdr.parent, TRUE )))) goto done; if (!SUCCESS((ret = create_con( con )))) goto done;
- ret = driver_connect_unix_a( con, WindowHandle, InConnectionString, Length, OutConnectionString, - BufferLength, Length2, DriverCompletion ); + ret = driver_connect_unix_a( con, WindowHandle, strA, Length, OutConnectionString, BufferLength, Length2, + DriverCompletion ); }
done: + free( strA ); + free( strW ); + free( connect_string ); + free_attribute_list( &attrs ); free( filename ); - free( datasource ); - free( drivername );
TRACE("Returning %d\n", ret); unlock_object( &con->hdr ); @@ -6484,7 +6583,9 @@ SQLRETURN WINAPI SQLDriverConnectW(SQLHDBC ConnectionHandle, SQLHWND WindowHandl SQLSMALLINT *Length2, SQLUSMALLINT DriverCompletion) { struct connection *con = (struct connection *)lock_object( ConnectionHandle, SQL_HANDLE_DBC ); - WCHAR *datasource, *drivername = NULL, *filename = NULL; + const WCHAR *datasource, *drivername = NULL; + WCHAR *filename = NULL, *connect_string = NULL; + struct attribute_list attrs; SQLRETURN ret = SQL_ERROR;
TRACE("(ConnectionHandle %p, WindowHandle %p, InConnectionString %s, Length %d, OutConnectionString %p," @@ -6494,7 +6595,10 @@ SQLRETURN WINAPI SQLDriverConnectW(SQLHDBC ConnectionHandle, SQLHWND WindowHandl
if (!con) return SQL_INVALID_HANDLE;
- if (!(datasource = get_datasource( InConnectionString )) && !(drivername = get_drivername( InConnectionString ))) + if (parse_connect_string( &attrs, InConnectionString ) || !(connect_string = build_connect_string( &attrs ))) + goto done; + + if (!(datasource = get_datasource( &attrs )) && !(drivername = get_drivername( &attrs ))) { WARN( "can't find data source or driver name\n" ); goto done; @@ -6533,9 +6637,9 @@ SQLRETURN WINAPI SQLDriverConnectW(SQLHDBC ConnectionHandle, SQLHWND WindowHandl }
done: + free( connect_string ); + free_attribute_list( &attrs ); free( filename ); - free( datasource ); - free( drivername );
TRACE("Returning %d\n", ret); unlock_object( &con->hdr ); @@ -6912,7 +7016,9 @@ SQLRETURN WINAPI SQLBrowseConnectW(SQLHDBC ConnectionHandle, SQLWCHAR *InConnect SQLWCHAR *OutConnectionString, SQLSMALLINT BufferLength, SQLSMALLINT *StringLength2) { struct connection *con = (struct connection *)lock_object( ConnectionHandle, SQL_HANDLE_DBC ); - WCHAR *datasource, *drivername = NULL, *filename = NULL; + const WCHAR *datasource, *drivername = NULL; + WCHAR *filename = NULL, *connect_string = NULL; + struct attribute_list attrs; SQLRETURN ret = SQL_ERROR;
TRACE("(ConnectionHandle %p, InConnectionString %s, StringLength1 %d, OutConnectionString %p, BufferLength %d, " @@ -6921,7 +7027,10 @@ SQLRETURN WINAPI SQLBrowseConnectW(SQLHDBC ConnectionHandle, SQLWCHAR *InConnect
if (!con) return SQL_INVALID_HANDLE;
- if (!(datasource = get_datasource( InConnectionString )) && !(drivername = get_drivername( InConnectionString ))) + if (parse_connect_string( &attrs, InConnectionString ) || !(connect_string = build_connect_string( &attrs ))) + goto done; + + if (!(datasource = get_datasource( &attrs )) && !(drivername = get_drivername( &attrs ))) { WARN( "can't find data source or driver name\n" ); goto done; @@ -6945,7 +7054,7 @@ SQLRETURN WINAPI SQLBrowseConnectW(SQLHDBC ConnectionHandle, SQLWCHAR *InConnect if (!SUCCESS((ret = create_env( (struct environment *)con->hdr.parent, FALSE )))) goto done; if (!SUCCESS((ret = create_con( con )))) goto done;
- ret = browse_connect_win32_w( con, InConnectionString, StringLength1, OutConnectionString, BufferLength, + ret = browse_connect_win32_w( con, connect_string, StringLength1, OutConnectionString, BufferLength, StringLength2 ); } else @@ -6955,14 +7064,14 @@ SQLRETURN WINAPI SQLBrowseConnectW(SQLHDBC ConnectionHandle, SQLWCHAR *InConnect if (!SUCCESS((ret = create_env( (struct environment *)con->hdr.parent, TRUE )))) goto done; if (!SUCCESS((ret = create_con( con )))) goto done;
- ret = browse_connect_unix_w( con, InConnectionString, StringLength1, OutConnectionString, BufferLength, + ret = browse_connect_unix_w( con, connect_string, StringLength1, OutConnectionString, BufferLength, StringLength2 ); }
done: + free( connect_string ); + free_attribute_list( &attrs ); free( filename ); - free( datasource ); - free( drivername );
TRACE("Returning %d\n", ret); unlock_object( &con->hdr ); diff --git a/dlls/odbc32/tests/odbc32.c b/dlls/odbc32/tests/odbc32.c index 7fdeb0ee75d..343220771f1 100644 --- a/dlls/odbc32/tests/odbc32.c +++ b/dlls/odbc32/tests/odbc32.c @@ -182,7 +182,8 @@ static void test_SQLDriverConnect( void )
len = 0; str[0] = 0; - ret = SQLDriverConnect( con, NULL, (SQLCHAR *)"DSN=winetest", strlen("DSN=winetest"), str, sizeof(str), &len, 0 ); + ret = SQLDriverConnect( con, NULL, (SQLCHAR *)"DSN=winetest;UID=winetest", strlen("DSN=winetest;UID=winetest"), + str, sizeof(str), &len, 0 ); if (ret == SQL_ERROR) diag( con, SQL_HANDLE_DBC ); if (ret != SQL_SUCCESS) { @@ -191,6 +192,26 @@ static void test_SQLDriverConnect( void ) skip( "data source winetest not available\n" ); return; } + ok( ret == SQL_SUCCESS, "got %d\n", ret ); + todo_wine { + ok( !strcmp( (const char *)str, "DSN=winetest;UID=winetest;" ), "got '%s'\n", str ); + ok( len == 26, "got %d\n", len ); + } + + ret = SQLDisconnect( con ); + ok( ret == SQL_SUCCESS, "got %d\n", ret ); + + /* trailing garbage */ + len = 0; + str[0] = 0; + ret = SQLDriverConnect( con, NULL, (SQLCHAR *)"DSN=winetest;er\9.99", strlen("DSN=winetest;er\9.99"), + str, sizeof(str), &len, 0 ); + if (ret == SQL_ERROR) diag( con, SQL_HANDLE_DBC ); + ok( ret == SQL_SUCCESS, "got %d\n", ret ); + todo_wine { + ok( !strcmp( (const char *)str, "DSN=winetest;" ), "got '%s'\n", str ); + ok( len == 13, "got %d\n", len ); + }
ret = SQLDisconnect( con ); ok( ret == SQL_SUCCESS, "got %d\n", ret ); @@ -227,6 +248,9 @@ static void test_SQLBrowseConnect( void ) skip( "data source winetest not available\n" ); return; } + ok( ret == SQL_SUCCESS, "got %d\n", ret ); + ok( !strcmp( (const char *)str, "DSN=winetest" ), "got '%s'\n", str ); + ok( len == 12, "got %d\n", len );
ret = SQLDisconnect( con ); ok( ret == SQL_SUCCESS, "got %d\n", ret );
From: Hans Leidekker hans@codeweavers.com
--- dlls/odbc32/proxyodbc.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/dlls/odbc32/proxyodbc.c b/dlls/odbc32/proxyodbc.c index 7388cfb3d9c..58405c94d60 100644 --- a/dlls/odbc32/proxyodbc.c +++ b/dlls/odbc32/proxyodbc.c @@ -3009,7 +3009,11 @@ SQLRETURN WINAPI SQLGetStmtAttr(SQLHSTMT StatementHandle, SQLINTEGER Attribute, ERR( "truncating descriptor handle, consider using a Windows driver\n" ); desc->hdr.unix_handle = (ULONG_PTR)*(SQLHDESC *)Value; } - else if (stmt->hdr.win32_handle) desc->hdr.win32_handle = *(SQLHDESC *)Value; + else if (stmt->hdr.win32_handle) + { + desc->hdr.win32_handle = *(SQLHDESC *)Value; + desc->hdr.win32_funcs = stmt->hdr.win32_funcs; + } *(struct descriptor **)Value = desc; break; } @@ -6428,7 +6432,11 @@ SQLRETURN WINAPI SQLGetStmtAttrW(SQLHSTMT StatementHandle, SQLINTEGER Attribute, ERR( "truncating descriptor handle, consider using a Windows driver\n" ); desc->hdr.unix_handle = (ULONG_PTR)*(SQLHDESC *)Value; } - else if (stmt->hdr.win32_handle) desc->hdr.win32_handle = *(SQLHDESC *)Value; + else if (stmt->hdr.win32_handle) + { + desc->hdr.win32_handle = *(SQLHDESC *)Value; + desc->hdr.win32_funcs = stmt->hdr.win32_funcs; + } *(struct descriptor **)Value = desc; break; }
From: Hans Leidekker hans@codeweavers.com
--- dlls/odbc32/proxyodbc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/odbc32/proxyodbc.c b/dlls/odbc32/proxyodbc.c index 58405c94d60..bbb0e1702ae 100644 --- a/dlls/odbc32/proxyodbc.c +++ b/dlls/odbc32/proxyodbc.c @@ -6424,6 +6424,8 @@ SQLRETURN WINAPI SQLGetStmtAttrW(SQLHSTMT StatementHandle, SQLINTEGER Attribute, { case SQL_ATTR_APP_ROW_DESC: case SQL_ATTR_APP_PARAM_DESC: + case SQL_ATTR_IMP_ROW_DESC: + case SQL_ATTR_IMP_PARAM_DESC: { struct descriptor *desc = stmt->desc[Attribute - SQL_ATTR_APP_ROW_DESC]; if (stmt->hdr.unix_handle) @@ -7668,8 +7670,6 @@ SQLRETURN WINAPI SQLSetStmtAttrW(SQLHSTMT StatementHandle, SQLINTEGER Attribute, { case SQL_ATTR_APP_ROW_DESC: case SQL_ATTR_APP_PARAM_DESC: - case SQL_ATTR_IMP_ROW_DESC: - case SQL_ATTR_IMP_PARAM_DESC: { struct descriptor *desc = (struct descriptor *)lock_object( Value, SQL_HANDLE_DESC ); if (desc)
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=147734
Your paranoid android.
=== debian11b (64 bit WoW report) ===
user32: input.c:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 0000000001D900E0, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032