SQLFreeSTMT doesn't use the generic function as it cause a crash when the FreeHandle was called (mysql).
From: Alistair Leslie-Hughes leslie_alistair@hotmail.com
--- dlls/odbc32/proxyodbc.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-)
diff --git a/dlls/odbc32/proxyodbc.c b/dlls/odbc32/proxyodbc.c index b71ef7aac42..2a38197b243 100644 --- a/dlls/odbc32/proxyodbc.c +++ b/dlls/odbc32/proxyodbc.c @@ -1401,6 +1401,37 @@ SQLRETURN WINAPI SQLFetchScroll(SQLHSTMT StatementHandle, SQLSMALLINT FetchOrien return ret; }
+static SQLRETURN freehandle_win32(struct handle *handle, SQLSMALLINT type, SQLUSMALLINT option) +{ + SQLRETURN ret = SQL_ERROR; + + if (handle->win32_funcs->SQLFreeHandle) + { + ret = handle->win32_funcs->SQLFreeHandle( type, handle->win32_handle ); + } + else + { + /* ODBC v2 */ + if (type == SQL_HANDLE_ENV) + { + if (handle->win32_funcs->SQLFreeEnv) + ret = handle->win32_funcs->SQLFreeEnv( handle->win32_handle ); + } + else if (type == SQL_HANDLE_DBC) + { + if (handle->win32_funcs->SQLFreeConnect) + ret = handle->win32_funcs->SQLFreeConnect( handle->win32_handle ); + } + else if (type == SQL_HANDLE_STMT) + { + if (handle->win32_funcs->SQLFreeStmt) + ret = handle->win32_funcs->SQLFreeStmt( handle->win32_handle, option ); + } + } + + return ret; +} + /************************************************************************* * SQLFreeConnect [ODBC32.014] */ @@ -1420,7 +1451,7 @@ SQLRETURN WINAPI SQLFreeConnect(SQLHDBC ConnectionHandle) } else if (handle->win32_handle) { - ret = handle->win32_funcs->SQLFreeHandle( SQL_HANDLE_DBC, handle->win32_handle ); + ret = freehandle_win32( handle, SQL_HANDLE_DBC, 0 ); }
free( handle ); @@ -1447,7 +1478,7 @@ SQLRETURN WINAPI SQLFreeEnv(SQLHENV EnvironmentHandle) } else if (handle->win32_handle) { - ret = handle->win32_funcs->SQLFreeHandle( SQL_HANDLE_ENV, handle->win32_handle ); + ret = freehandle_win32( handle, SQL_HANDLE_ENV, 0 ); }
RegCloseKey( handle->drivers_key ); @@ -1497,7 +1528,7 @@ SQLRETURN WINAPI SQLFreeHandle(SQLSMALLINT HandleType, SQLHANDLE Handle) } else if (handle->win32_handle) { - ret = handle->win32_funcs->SQLFreeHandle( HandleType, handle->win32_handle ); + ret = freehandle_win32( handle, HandleType, 0 ); }
RegCloseKey( handle->drivers_key );
From: Alistair Leslie-Hughes leslie_alistair@hotmail.com
--- dlls/odbc32/proxyodbc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/dlls/odbc32/proxyodbc.c b/dlls/odbc32/proxyodbc.c index 2a38197b243..741555f6582 100644 --- a/dlls/odbc32/proxyodbc.c +++ b/dlls/odbc32/proxyodbc.c @@ -839,7 +839,7 @@ static int has_suffix( const WCHAR *str, const WCHAR *suffix )
static SQLRETURN set_env_attr( struct handle *handle, SQLINTEGER attr, SQLPOINTER value, SQLINTEGER len ) { - SQLRETURN ret = SQL_ERROR; + SQLRETURN ret = SQL_SUCCESS;
if (handle->unix_handle) { @@ -848,7 +848,8 @@ static SQLRETURN set_env_attr( struct handle *handle, SQLINTEGER attr, SQLPOINTE } else if (handle->win32_handle) { - ret = handle->win32_funcs->SQLSetEnvAttr( handle->win32_handle, attr, value, len ); + if (handle->win32_funcs->SQLSetEnvAttr) + ret = handle->win32_funcs->SQLSetEnvAttr( handle->win32_handle, attr, value, len ); } return ret; }
From: Alistair Leslie-Hughes leslie_alistair@hotmail.com
--- dlls/odbc32/proxyodbc.c | 42 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-)
diff --git a/dlls/odbc32/proxyodbc.c b/dlls/odbc32/proxyodbc.c index 741555f6582..e8e08fb7d00 100644 --- a/dlls/odbc32/proxyodbc.c +++ b/dlls/odbc32/proxyodbc.c @@ -410,6 +410,38 @@ SQLRETURN WINAPI SQLAllocEnv(SQLHENV *EnvironmentHandle) return ret; }
+static SQLRETURN allochandle_win32(struct handle *handle, SQLSMALLINT type, SQLHANDLE InputHandle, SQLHANDLE *OutputHandle) +{ + SQLRETURN ret = SQL_ERROR; + + if (handle->win32_funcs->SQLAllocHandle) + { + if ((ret = handle->win32_funcs->SQLAllocHandle( type, InputHandle, OutputHandle ))) + return ret; + } + else + { + /* ODBC v2 */ + if (type == SQL_HANDLE_ENV) + { + if (handle->win32_funcs->SQLAllocEnv) + ret = handle->win32_funcs->SQLAllocEnv( OutputHandle ); + } + else if (type == SQL_HANDLE_DBC) + { + if (handle->win32_funcs->SQLAllocConnect) + ret = handle->win32_funcs->SQLAllocConnect( InputHandle, OutputHandle ); + } + else if (type == SQL_HANDLE_STMT) + { + if (handle->win32_funcs->SQLAllocStmt) + ret = handle->win32_funcs->SQLAllocStmt( InputHandle, OutputHandle ); + } + } + + return ret; +} + /************************************************************************* * SQLAllocHandle [ODBC32.024] */ @@ -438,7 +470,7 @@ SQLRETURN WINAPI SQLAllocHandle(SQLSMALLINT HandleType, SQLHANDLE InputHandle, S } else if (input->win32_handle) { - ret = input->win32_funcs->SQLAllocHandle( HandleType, input->win32_handle, &output->win32_handle ); + ret = allochandle_win32(input, HandleType, input->win32_handle, &output->win32_handle); if (SUCCESS( ret )) output->win32_funcs = input->win32_funcs; }
@@ -469,7 +501,7 @@ SQLRETURN WINAPI SQLAllocStmt(SQLHDBC ConnectionHandle, SQLHSTMT *StatementHandl } else if (con->win32_handle) { - ret = con->win32_funcs->SQLAllocStmt( con->win32_handle, &stmt->win32_handle ); + ret = allochandle_win32(con, SQL_HANDLE_STMT, con->win32_handle, &stmt->win32_handle ); if (SUCCESS( ret )) stmt->win32_funcs = con->win32_funcs; }
@@ -508,7 +540,7 @@ SQLRETURN WINAPI SQLAllocHandleStd(SQLSMALLINT HandleType, SQLHANDLE InputHandle } else if (input->win32_handle) { - ret = input->win32_funcs->SQLAllocHandleStd( HandleType, input->win32_handle, &output->win32_handle ); + ret = allochandle_win32(input, HandleType, input->win32_handle, &output->win32_handle); if (SUCCESS( ret )) output->win32_funcs = input->win32_funcs; }
@@ -874,7 +906,7 @@ static SQLRETURN create_env( struct handle *handle, BOOL is_unix ) } else { - if ((ret = handle->win32_funcs->SQLAllocHandle( SQL_HANDLE_ENV, NULL, &handle->win32_handle ))) return ret; + if ((ret = allochandle_win32(handle, SQL_HANDLE_ENV, NULL, &handle->win32_handle ))) return ret; }
return prepare_env( handle ); @@ -930,7 +962,7 @@ static SQLRETURN create_con( struct handle *handle ) } else { - if ((ret = handle->win32_funcs->SQLAllocHandle( SQL_HANDLE_DBC, parent->win32_handle, &handle->win32_handle ))) + if ((ret = allochandle_win32(handle, SQL_HANDLE_DBC, parent->win32_handle, &handle->win32_handle ))) return ret; }
Hans Leidekker (@hans) commented about dlls/odbc32/proxyodbc.c:
} else if (input->win32_handle) {
ret = input->win32_funcs->SQLAllocHandle( HandleType, input->win32_handle, &output->win32_handle );
ret = allochandle_win32(input, HandleType, input->win32_handle, &output->win32_handle);
This is emulating a v3 function (SQLAllocHandle()) with v2 functions (SQLAllocEnv()/..). Is that what native does? Is your app calling SQLAllocHandle() or is it us? In the latter case we may just need to handle that differently.
On Thu Jul 18 09:12:11 2024 +0000, Hans Leidekker wrote:
This is emulating a v3 function (SQLAllocHandle()) with v2 functions (SQLAllocEnv()/..). Is that what native does? Is your app calling SQLAllocHandle() or is it us? In the latter case we may just need to handle that differently.
The application is calling SQLAllocHandle but the underlying driver only implements SQLAllocEnv/SQLAllocConnect and not SQLAllocHandle.
For reference, this basically states the behavior implemented. https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/mapping-rep...
On Thu Jul 18 09:27:07 2024 +0000, Alistair Leslie-Hughes wrote:
The application is calling SQLAllocHandle but the underlying driver only implements SQLAllocEnv/SQLAllocConnect and not SQLAllocHandle. For reference, this basically states the behavior implemented. https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/mapping-rep...
I see. Mapping v3 to v2 can only be partial however, so I wonder how the application handles that.
On Thu Jul 18 09:43:43 2024 +0000, Hans Leidekker wrote:
I see. Mapping v3 to v2 can only be partial however, so I wonder how the application handles that.
Not sure where you going but as long as the v3 functions can call the avialable fallback v2 functions. The the application shouldn't care.
The only time they is going to be an issue is if the fallback doesn't exist.
On Thu Jul 18 10:03:45 2024 +0000, Alistair Leslie-Hughes wrote:
Not sure where you going but as long as the v3 functions can call the avialable fallback v2 functions. The the application shouldn't care. The only time they is going to be an issue is if the fallback doesn't exist.
Right, the fallback may not exist. If the application uses v3 functions with a v2 driver it has to know which v3 functions are available. Anyway, I think the reverse case is the more interesting one, mapping v2 functions to v3. Most drivers support v3 these days but not all applications will have been ported to v3.
On Thu Jul 18 10:17:47 2024 +0000, Hans Leidekker wrote:
Right, the fallback may not exist. If the application uses v3 functions with a v2 driver it has to know which v3 functions are available. Anyway, I think the reverse case is the more interesting one, mapping v2 functions to v3. Most drivers support v3 these days but not all applications will have been ported to v3.
Old database applications still work on windows, which suggest fall backs are in play no matter which ODBC32 functions are used.
Applications don't need to know what functions are available at the driver level. That up to ODBC32 to work the best available function(s) for the given call. The only things the might vary are the options or datatypes available. (eg type SQL_C_TYPE_TIME isn't supported for v2).
For an application, It doesn't matter if ODBC32 uses SQLAllocEnv() or SQLAllocaHandle() under the hood as long a Environment Handle is returned (example).