/* * odbcStubInit.c -- * * Stubs tables for the foreign ODBC libraries so that * Tcl extensions can use them without the linker's knowing about them. * * @CREATED@ 2018-05-12 16:18:48Z by genExtStubs.tcl from odbcStubDefs.txt * * Copyright (c) 2010 by Kevin B. Kenny. * * Please refer to the file, 'license.terms' for the conditions on * redistribution of this file and for a DISCLAIMER OF ALL WARRANTIES. * *----------------------------------------------------------------------------- */ #include #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include #endif #include "fakesql.h" #if defined(_WIN32) && defined(_MSC_VER) && _MSC_VER < 1900 # define snprintf _snprintf #endif /* * Static data used in this file */ /* * Names of the libraries that might contain the ODBC API */ static const char *const odbcStubLibNames[] = { #if defined(__APPLE__) "libiodbc.2", #elif defined(__OpenBSD__) "libiodbc", #else "odbc32", "odbc", "libodbc32", "libodbc", "libiodbc", #endif NULL /* @END@ */ }; static const char *const odbcOptLibNames[] = { #if defined(__APPLE__) "libiodbcinst.2", #elif defined(__OpenBSD__) "libiodbcinst", #else "odbccp", "odbccp32", "odbcinst", "libodbccp", "libodbccp32", "libodbcinst", "libiodbcinst", #endif NULL }; /* * Names of the functions that we need from ODBC */ static const char *const odbcSymbolNames[] = { /* @SYMNAMES@: DO NOT EDIT THESE NAMES */ "SQLAllocHandle", "SQLBindParameter", "SQLCloseCursor", "SQLColumnsW", "SQLDataSourcesW", "SQLDescribeColW", "SQLDescribeParam", "SQLDisconnect", "SQLDriverConnectW", "SQLDriversW", "SQLEndTran", "SQLExecute", "SQLFetch", "SQLForeignKeysW", "SQLFreeHandle", "SQLGetConnectAttr", "SQLGetData", "SQLGetDiagFieldA", "SQLGetDiagRecW", "SQLGetInfoW", "SQLGetTypeInfo", "SQLMoreResults", "SQLNumParams", "SQLNumResultCols", "SQLPrepareW", "SQLPrimaryKeysW", "SQLRowCount", "SQLSetConnectAttr", "SQLSetConnectOption", "SQLSetEnvAttr", "SQLTablesW", "SQLExecDirectW", NULL /* @END@ */ }; /* * Table containing pointers to the functions named above. */ static odbcStubDefs odbcStubsTable; const odbcStubDefs* odbcStubs = &odbcStubsTable; /* * Pointers to optional functions in ODBCINST */ BOOL (INSTAPI* SQLConfigDataSourceW)(HWND, WORD, LPCWSTR, LPCWSTR) = NULL; BOOL (INSTAPI* SQLConfigDataSource)(HWND, WORD, LPCSTR, LPCSTR) = NULL; BOOL (INSTAPI* SQLInstallerError)(WORD, DWORD*, LPSTR, WORD, WORD*) = NULL; /* *----------------------------------------------------------------------------- * * OdbcInitStubs -- * * Initialize the Stubs table for the ODBC API * * Results: * Returns the handle to the loaded ODBC client library, or NULL * if the load is unsuccessful. Leaves an error message in the * interpreter. * *----------------------------------------------------------------------------- */ MODULE_SCOPE Tcl_LoadHandle OdbcInitStubs(Tcl_Interp* interp, /* Tcl interpreter */ Tcl_LoadHandle* handle2Ptr) /* Pointer to a second load handle * that represents the ODBCINST library */ { int i; int status; /* Status of Tcl library calls */ Tcl_Obj* path; /* Path name of a module to be loaded */ Tcl_Obj* shlibext; /* Extension to use for load modules */ Tcl_LoadHandle handle = NULL; /* Handle to a load module */ SQLConfigDataSourceW = NULL; SQLConfigDataSource = NULL; SQLInstallerError = NULL; #if !defined(_WIN32) && !defined(__APPLE__) && !defined(__OpenBSD__) int abiNum = 2; #endif /* * Determine the shared library extension */ status = Tcl_EvalEx(interp, "::info sharedlibextension", -1, TCL_EVAL_GLOBAL); if (status != TCL_OK) return NULL; shlibext = Tcl_GetObjResult(interp); Tcl_IncrRefCount(shlibext); /* * Walk the list of possible library names to find an ODBC client */ status = TCL_ERROR; #if !defined(_WIN32) && !defined(__APPLE__) && !defined(__OpenBSD__) again: #endif for (i = 0; status == TCL_ERROR && odbcStubLibNames[i] != NULL; ++i) { path = Tcl_NewStringObj(odbcStubLibNames[i], -1); Tcl_AppendObjToObj(path, shlibext); #if !defined(_WIN32) && !defined(__APPLE__) && !defined(__OpenBSD__) if (abiNum != 0) { char abiBuffer[16]; snprintf(abiBuffer, sizeof(abiBuffer), ".%d", abiNum); Tcl_AppendObjToObj(path, Tcl_NewStringObj(abiBuffer, -1)); } #endif Tcl_IncrRefCount(path); Tcl_ResetResult(interp); /* * Try to load a client library and resolve the ODBC API within it. */ status = Tcl_LoadFile(interp, path, odbcSymbolNames, 0, (void*)odbcStubs, &handle); Tcl_DecrRefCount(path); } #if !defined(_WIN32) && !defined(__APPLE__) && !defined(__OpenBSD__) if (status == TCL_ERROR) { if (--abiNum >= 0) { goto again; } } #endif /* * If a client library is found, then try to load ODBCINST as well. */ if (status == TCL_OK) { int status2 = TCL_ERROR; for (i = 0; status2 == TCL_ERROR && odbcOptLibNames[i] != NULL; ++i) { path = Tcl_NewStringObj(odbcOptLibNames[i], -1); Tcl_AppendObjToObj(path, shlibext); #if !defined(_WIN32) && !defined(__APPLE__) && !defined(__OpenBSD__) if (abiNum != 0) { char abiBuffer[16]; snprintf(abiBuffer, sizeof(abiBuffer), ".%d", abiNum); Tcl_AppendObjToObj(path, Tcl_NewStringObj(abiBuffer, -1)); } #endif Tcl_IncrRefCount(path); status2 = Tcl_LoadFile(interp, path, NULL, 0, NULL, handle2Ptr); if (status2 == TCL_OK) { SQLConfigDataSourceW = (BOOL (INSTAPI*)(HWND, WORD, LPCWSTR, LPCWSTR)) Tcl_FindSymbol(NULL, *handle2Ptr, "SQLConfigDataSourceW"); if (SQLConfigDataSourceW == NULL) { SQLConfigDataSource = (BOOL (INSTAPI*)(HWND, WORD, LPCSTR, LPCSTR)) Tcl_FindSymbol(NULL, *handle2Ptr, "SQLConfigDataSource"); } SQLInstallerError = (BOOL (INSTAPI*)(WORD, DWORD*, LPSTR, WORD, WORD*)) Tcl_FindSymbol(NULL, *handle2Ptr, "SQLInstallerError"); } else { Tcl_ResetResult(interp); } Tcl_DecrRefCount(path); } } /* * Either we've successfully loaded a library (status == TCL_OK), * or we've run out of library names (in which case status==TCL_ERROR * and the error message reflects the last unsuccessful load attempt). */ Tcl_DecrRefCount(shlibext); if (status != TCL_OK) { return NULL; } return handle; }