📄 proxyodbc.c
字号:
/*
* Win32 ODBC functions
*
* Copyright 1999 Xiang Li, Corel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* NOTES:
* Proxy ODBC driver manager. This manager delegates all ODBC
* calls to a real ODBC driver manager named by the environment
* variable LIB_ODBC_DRIVER_MANAGER, or to libodbc.so if the
* variable is not set.
*
*/
#include "config.h"
#include "wine/port.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "windef.h"
#include "winbase.h"
#include "wine/debug.h"
//#include "wine/library.h"
#include "sql.h"
#include "sqltypes.h"
#include "sqlext.h"
#include "proxyodbc.h"
static BOOL ODBC_LoadDriverManager(void);
static BOOL ODBC_LoadDMFunctions(void);
WINE_DEFAULT_DEBUG_CHANNEL(odbc);
static const DM_FUNC template_func[] =
{
/* 00 */ { SQL_API_SQLALLOCCONNECT, "SQLAllocConnect", SQLAllocConnect, NULL },
/* 01 */ { SQL_API_SQLALLOCENV, "SQLAllocEnv", SQLAllocEnv, NULL },
/* 02 */ { SQL_API_SQLALLOCHANDLE, "SQLAllocHandle", SQLAllocHandle, NULL },
/* 03 */ { SQL_API_SQLALLOCSTMT, "SQLAllocStmt", SQLAllocStmt, NULL },
/* 04 */ { SQL_API_SQLALLOCHANDLESTD, "SQLAllocHandleStd", SQLAllocHandleStd, NULL },
/* 05 */ { SQL_API_SQLBINDCOL, "SQLBindCol", SQLBindCol, NULL },
/* 06 */ { SQL_API_SQLBINDPARAM, "SQLBindParam", SQLBindParam, NULL },
/* 07 */ { SQL_API_SQLBINDPARAMETER, "SQLBindParameter", SQLBindParameter, NULL },
/* 08 */ { SQL_API_SQLBROWSECONNECT, "SQLBrowseConnect", SQLBrowseConnect, NULL },
/* 09 */ { SQL_API_SQLBULKOPERATIONS, "SQLBulkOperations", SQLBulkOperations, NULL },
/* 10 */ { SQL_API_SQLCANCEL, "SQLCancel", SQLCancel, NULL },
/* 11 */ { SQL_API_SQLCLOSECURSOR, "SQLCloseCursor", SQLCloseCursor, NULL },
/* 12 */ { SQL_API_SQLCOLATTRIBUTE, "SQLColAttribute", SQLColAttribute, NULL },
/* 13 */ { SQL_API_SQLCOLATTRIBUTES, "SQLColAttributes", SQLColAttributes, NULL },
/* 14 */ { SQL_API_SQLCOLUMNPRIVILEGES, "SQLColumnPrivileges", SQLColumnPrivileges, NULL },
/* 15 */ { SQL_API_SQLCOLUMNS, "SQLColumns", SQLColumns, NULL },
/* 16 */ { SQL_API_SQLCONNECT, "SQLConnect", SQLConnect, NULL },
/* 17 */ { SQL_API_SQLCOPYDESC, "SQLCopyDesc", SQLCopyDesc, NULL },
/* 18 */ { SQL_API_SQLDATASOURCES, "SQLDataSources", SQLDataSources, NULL },
/* 19 */ { SQL_API_SQLDESCRIBECOL, "SQLDescribeCol", SQLDescribeCol, NULL },
/* 20 */ { SQL_API_SQLDESCRIBEPARAM, "SQLDescribeParam", SQLDescribeParam, NULL },
/* 21 */ { SQL_API_SQLDISCONNECT, "SQLDisconnect", SQLDisconnect, NULL },
/* 22 */ { SQL_API_SQLDRIVERCONNECT, "SQLDriverConnect", SQLDriverConnect, NULL },
/* 23 */ { SQL_API_SQLDRIVERS, "SQLDrivers", SQLDrivers, NULL },
/* 24 */ { SQL_API_SQLENDTRAN, "SQLEndTran", SQLEndTran, NULL },
/* 25 */ { SQL_API_SQLERROR, "SQLError", SQLError, NULL },
/* 26 */ { SQL_API_SQLEXECDIRECT, "SQLExecDirect", SQLExecDirect, NULL },
/* 27 */ { SQL_API_SQLEXECUTE, "SQLExecute", SQLExecute, NULL },
/* 28 */ { SQL_API_SQLEXTENDEDFETCH, "SQLExtendedFetch", SQLExtendedFetch, NULL },
/* 29 */ { SQL_API_SQLFETCH, "SQLFetch", SQLFetch, NULL },
/* 30 */ { SQL_API_SQLFETCHSCROLL, "SQLFetchScroll", SQLFetchScroll, NULL },
/* 31 */ { SQL_API_SQLFOREIGNKEYS, "SQLForeignKeys", SQLForeignKeys, NULL },
/* 32 */ { SQL_API_SQLFREEENV, "SQLFreeEnv", SQLFreeEnv, NULL },
/* 33 */ { SQL_API_SQLFREEHANDLE, "SQLFreeHandle", SQLFreeHandle, NULL },
/* 34 */ { SQL_API_SQLFREESTMT, "SQLFreeStmt", SQLFreeStmt, NULL },
/* 35 */ { SQL_API_SQLFREECONNECT, "SQLFreeConnect", SQLFreeConnect, NULL },
/* 36 */ { SQL_API_SQLGETCONNECTATTR, "SQLGetConnectAttr", SQLGetConnectAttr, NULL },
/* 37 */ { SQL_API_SQLGETCONNECTOPTION, "SQLGetConnectOption", SQLGetConnectOption, NULL },
/* 38 */ { SQL_API_SQLGETCURSORNAME, "SQLGetCursorName", SQLGetCursorName, NULL },
/* 39 */ { SQL_API_SQLGETDATA, "SQLGetData", SQLGetData, NULL },
/* 40 */ { SQL_API_SQLGETDESCFIELD, "SQLGetDescField", SQLGetDescField, NULL },
/* 41 */ { SQL_API_SQLGETDESCREC, "SQLGetDescRec", SQLGetDescRec, NULL },
/* 42 */ { SQL_API_SQLGETDIAGFIELD, "SQLGetDiagField", SQLGetDiagField, NULL },
/* 43 */ { SQL_API_SQLGETENVATTR, "SQLGetEnvAttr", SQLGetEnvAttr, NULL },
/* 44 */ { SQL_API_SQLGETFUNCTIONS, "SQLGetFunctions", SQLGetFunctions, NULL },
/* 45 */ { SQL_API_SQLGETINFO, "SQLGetInfo", SQLGetInfo, NULL },
/* 46 */ { SQL_API_SQLGETSTMTATTR, "SQLGetStmtAttr", SQLGetStmtAttr, NULL },
/* 47 */ { SQL_API_SQLGETSTMTOPTION, "SQLGetStmtOption", SQLGetStmtOption, NULL },
/* 48 */ { SQL_API_SQLGETTYPEINFO, "SQLGetTypeInfo", SQLGetTypeInfo, NULL },
/* 49 */ { SQL_API_SQLMORERESULTS, "SQLMoreResults", SQLMoreResults, NULL },
/* 50 */ { SQL_API_SQLNATIVESQL, "SQLNativeSql", SQLNativeSql, NULL },
/* 51 */ { SQL_API_SQLNUMPARAMS, "SQLNumParams", SQLNumParams, NULL },
/* 52 */ { SQL_API_SQLNUMRESULTCOLS, "SQLNumResultCols", SQLNumResultCols, NULL },
/* 53 */ { SQL_API_SQLPARAMDATA, "SQLParamData", SQLParamData, NULL },
/* 54 */ { SQL_API_SQLPARAMOPTIONS, "SQLParamOptions", SQLParamOptions, NULL },
/* 55 */ { SQL_API_SQLPREPARE, "SQLPrepare", SQLPrepare, NULL },
/* 56 */ { SQL_API_SQLPRIMARYKEYS, "SQLPrimaryKeys", SQLPrimaryKeys, NULL },
/* 57 */ { SQL_API_SQLPROCEDURECOLUMNS, "SQLProcedureColumns", SQLProcedureColumns, NULL },
/* 58 */ { SQL_API_SQLPROCEDURES, "SQLProcedures", SQLProcedures, NULL },
/* 59 */ { SQL_API_SQLPUTDATA, "SQLPutData", SQLPutData, NULL },
/* 60 */ { SQL_API_SQLROWCOUNT, "SQLRowCount", SQLRowCount, NULL },
/* 61 */ { SQL_API_SQLSETCONNECTATTR, "SQLSetConnectAttr", SQLSetConnectAttr, NULL },
/* 62 */ { SQL_API_SQLSETCONNECTOPTION, "SQLSetConnectOption", SQLSetConnectOption, NULL },
/* 63 */ { SQL_API_SQLSETCURSORNAME, "SQLSetCursorName", SQLSetCursorName, NULL },
/* 64 */ { SQL_API_SQLSETDESCFIELD, "SQLSetDescField", SQLSetDescField, NULL },
/* 65 */ { SQL_API_SQLSETDESCREC, "SQLSetDescRec", SQLSetDescRec, NULL },
/* 66 */ { SQL_API_SQLSETENVATTR, "SQLSetEnvAttr", SQLSetEnvAttr, NULL },
/* 67 */ { SQL_API_SQLSETPARAM, "SQLSetParam", SQLSetParam, NULL },
/* 68 */ { SQL_API_SQLSETPOS, "SQLSetPos", SQLSetPos, NULL },
/* 69 */ { SQL_API_SQLSETSCROLLOPTIONS, "SQLSetScrollOptions", SQLSetScrollOptions, NULL },
/* 70 */ { SQL_API_SQLSETSTMTATTR, "SQLSetStmtAttr", SQLSetStmtAttr, NULL },
/* 71 */ { SQL_API_SQLSETSTMTOPTION, "SQLSetStmtOption", SQLSetStmtOption, NULL },
/* 72 */ { SQL_API_SQLSPECIALCOLUMNS, "SQLSpecialColumns", SQLSpecialColumns, NULL },
/* 73 */ { SQL_API_SQLSTATISTICS, "SQLStatistics", SQLStatistics, NULL },
/* 74 */ { SQL_API_SQLTABLEPRIVILEGES, "SQLTablePrivileges", SQLTablePrivileges, NULL },
/* 75 */ { SQL_API_SQLTABLES, "SQLTables", SQLTables, NULL },
/* 76 */ { SQL_API_SQLTRANSACT, "SQLTransact", SQLTransact, NULL },
/* 77 */ { SQL_API_SQLGETDIAGREC, "SQLGetDiagRec", SQLGetDiagRec, NULL },
};
static PROXYHANDLE gProxyHandle;
/* What is the difference between these two (dmHandle cf READY_AND_dmHandle)? When does one use one and when the other? */
#define CHECK_dmHandle() \
{ \
if (gProxyHandle.dmHandle == NULL) \
{ \
TRACE ("Not ready\n"); \
return SQL_ERROR; \
} \
}
#define CHECK_READY_AND_dmHandle() \
{ \
if (!gProxyHandle.bFunctionReady || gProxyHandle.dmHandle == NULL) \
{ \
TRACE ("Not ready\n"); \
return SQL_ERROR; \
} \
}
SQLRETURN SQLDummyFunc()
{
TRACE("SQLDummyFunc: \n");
return SQL_SUCCESS;
}
/***********************************************************************
* DllMain [Internal] Initializes the internal 'ODBC32.DLL'.
*
* PARAMS
* hinstDLL [I] handle to the DLL's instance
* fdwReason [I]
* lpvReserved [I] reserved, must be NULL
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
int i;
TRACE("Initializing or Finalizing proxy ODBC: %p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
if (fdwReason == DLL_PROCESS_ATTACH)
{
TRACE("Loading ODBC...\n");
DisableThreadLibraryCalls(hinstDLL);
if (ODBC_LoadDriverManager())
ODBC_LoadDMFunctions();
}
else if (fdwReason == DLL_PROCESS_DETACH)
{
TRACE("Unloading ODBC...\n");
if (gProxyHandle.bFunctionReady)
{
for ( i = 0; i < NUM_SQLFUNC; i ++ )
{
gProxyHandle.functions[i].func = SQLDummyFunc;
}
}
#ifndef __REACTOS__
if (gProxyHandle.dmHandle)
{
wine_dlclose(gProxyHandle.dmHandle,NULL,0);
gProxyHandle.dmHandle = NULL;
}
#endif
}
return TRUE;
}
/***********************************************************************
* ODBC_LoadDriverManager [Internal] Load ODBC library.
*
* PARAMS
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
static BOOL ODBC_LoadDriverManager(void)
{
const char *s = getenv("LIB_ODBC_DRIVER_MANAGER");
char error[256];
TRACE("\n");
gProxyHandle.bFunctionReady = FALSE;
gProxyHandle.nErrorType = ERROR_LIBRARY_NOT_FOUND;
if (s!= NULL && strlen (s) >= sizeof(gProxyHandle.dmLibName))
{
ERR("Driver name too long (%s)\n",s);
return FALSE;
}
if (s == NULL || strlen(s) == 0)
s = "libodbc.so";
strcpy(gProxyHandle.dmLibName, s);
#ifndef __REACTOS__
gProxyHandle.dmHandle = wine_dlopen(gProxyHandle.dmLibName, RTLD_LAZY, error, sizeof(error));
if (gProxyHandle.dmHandle == NULL) /* fail to load unixODBC driver manager */
{
WARN("failed to open library %s: %s\n", gProxyHandle.dmLibName, error);
gProxyHandle.dmLibName[0] = '\0';
gProxyHandle.nErrorType = ERROR_LIBRARY_NOT_FOUND;
return FALSE;
}
else
{
gProxyHandle.nErrorType = ERROR_FREE;
return TRUE;
}
#else
return FALSE;
#endif
}
/***********************************************************************
* ODBC_LoadDMFunctions [Internal] Populate function table.
*
* PARAMS
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
static BOOL ODBC_LoadDMFunctions(void)
{
int i;
char error[256];
if (gProxyHandle.dmHandle == NULL)
return FALSE;
#ifndef __REACTOS__
for ( i = 0; i < NUM_SQLFUNC; i ++ )
{
gProxyHandle.functions[i] = template_func[i];
gProxyHandle.functions[i].func = wine_dlsym(gProxyHandle.dmHandle,
gProxyHandle.functions[i].name, error, sizeof(error));
if (error[0])
{
ERR("Failed to load function %s\n",gProxyHandle.functions[i].name);
gProxyHandle.functions[i].func = SQLDummyFunc;
}
}
gProxyHandle.bFunctionReady = TRUE;
#endif
return TRUE;
}
/*************************************************************************
* SQLAllocConnect [ODBC32.001]
*/
SQLRETURN WINAPI SQLAllocConnect(SQLHENV EnvironmentHandle, SQLHDBC *ConnectionHandle)
{
SQLRETURN ret;
TRACE("Env=%lx\n",EnvironmentHandle);
if (!gProxyHandle.bFunctionReady || gProxyHandle.dmHandle == NULL)
{
*ConnectionHandle = SQL_NULL_HDBC;
TRACE("Not ready\n");
return SQL_ERROR;
}
assert(gProxyHandle.functions[SQLAPI_INDEX_SQLALLOCCONNECT].func);
ret=(gProxyHandle.functions[SQLAPI_INDEX_SQLALLOCCONNECT].func)
(EnvironmentHandle, ConnectionHandle);
TRACE("Returns ret=%d, Handle %lx\n",ret, *ConnectionHandle);
return ret;
}
/*************************************************************************
* SQLAllocEnv [ODBC32.002]
*/
SQLRETURN WINAPI SQLAllocEnv(SQLHENV *EnvironmentHandle)
{
SQLRETURN ret;
TRACE("\n");
if (!gProxyHandle.bFunctionReady || gProxyHandle.dmHandle == NULL)
{
*EnvironmentHandle = SQL_NULL_HENV;
TRACE("Not ready\n");
return SQL_ERROR;
}
assert(gProxyHandle.functions[SQLAPI_INDEX_SQLALLOCENV].func);
ret=(gProxyHandle.functions[SQLAPI_INDEX_SQLALLOCENV].func) (EnvironmentHandle);
TRACE("Returns ret=%d, Env=%lx\n",ret, *EnvironmentHandle);
return ret;
}
/*************************************************************************
* SQLAllocHandle [ODBC32.024]
*/
SQLRETURN WINAPI SQLAllocHandle(SQLSMALLINT HandleType, SQLHANDLE InputHandle, SQLHANDLE *OutputHandle)
{
SQLRETURN ret;
TRACE("(Type=%d, Handle=%lx)\n",HandleType,InputHandle);
if (!gProxyHandle.bFunctionReady || gProxyHandle.dmHandle == NULL)
{
if (gProxyHandle.nErrorType == ERROR_LIBRARY_NOT_FOUND)
WARN("ProxyODBC: Can not load ODBC driver manager library.\n");
if (HandleType == SQL_HANDLE_ENV)
*OutputHandle = SQL_NULL_HENV;
else if (HandleType == SQL_HANDLE_DBC)
*OutputHandle = SQL_NULL_HDBC;
else if (HandleType == SQL_HANDLE_STMT)
*OutputHandle = SQL_NULL_HSTMT;
else if (HandleType == SQL_HANDLE_DESC)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -