⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 odbc.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*																			*
*						 cryptlib ODBC Mapping Routines						*
*						Copyright Peter Gutmann 1996-2007					*
*																			*
****************************************************************************/

#include <stdio.h>		/* For sprintf() */
#if defined( INC_ALL )
  #include "crypt.h"
  #include "keyset.h"
  #include "dbms.h"
#else
  #include "crypt.h"
  #include "keyset/keyset.h"
  #include "keyset/dbms.h"
#endif /* Compiler-specific includes */

/* ODBC functions can return either SQL_SUCCESS or SQL_SUCCESS_WITH_INFO to
   indicate successful completion, to make them easier to work with we use
   a general status-check macro along the lines of cryptStatusOK() */

#define sqlStatusOK( status ) \
		( ( status ) == SQL_SUCCESS || ( status ) == SQL_SUCCESS_WITH_INFO )

/* DBMS back-ends that require special handling */

enum { DBMS_NONE, DBMS_ACCESS, DBMS_INTERBASE, DBMS_POSTGRES };

/* The level at which we want SQLDiagRec() to return error information to 
   us */

typedef enum { SQL_ERRLVL_NONE, SQL_ERRLVL_STMT, SQL_ERRLVL_DBC, 
			   SQL_ERRLVL_ENV, SQL_ERRLVL_LAST } SQL_ERRLVL_TYPE;

/* When rewriting an SQL query we have to provide a slightly larger buffer 
   to allow for possible expansion of some SQL strings */

#define SQL_QUERY_BUFSIZE	( MAX_SQL_QUERY_SIZE + 64 )

#ifdef USE_ODBC

/* When processing bound data we need to store the state information used by 
   SQLBindParameter() until the SQL operation completes.  The following 
   structure provides the necessary state storage */

typedef struct {
	SQLINTEGER lengthStorage[ BOUND_DATA_MAXITEMS + 8 ];
	SQL_TIMESTAMP_STRUCT timestampStorage;
	} BOUND_DATA_STATE;

/****************************************************************************
*																			*
*						 		Init/Shutdown Routines						*
*																			*
****************************************************************************/

#ifdef DYNAMIC_LOAD

/* Global function pointers.  These are necessary because the functions need
   to be dynamically linked since not all systems contain the necessary
   shared libraries.  Explicitly linking to them will make cryptlib 
   unloadable on some systems.

   MSDN updates from late 2000 defined SQLROWCOUNT themselves (which could be
   fixed by undefining it), however after late 2002 the value was typedef'd,
   requring all sorts of extra trickery to handle the different cases.
   Because of this issue, this particular function is typedef'd with a _FN 
   suffix.
   
   Several of the ODBC functions allow such a mess of parameters, with 
   options for pointers to be cast to integers indexing a table of data 
   values hidden under someone's bed and other peculiarities, that several 
   of the following markups are only approximations for the way the 
   functions are used here.  If markups are absent entirely (e.g. for the
   SQLSetXXXAttr() functions) it's because the polymorphism of parameters 
   doesn't allow any coherent annotation to be given */

static INSTANCE_HANDLE hODBC = NULL_INSTANCE;

typedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLALLOCHANDLE )\
					( SQLSMALLINT HandleType, IN SQLHANDLE InputHandle, 
					OUT_PTR SQLHANDLE *OutputHandlePtr );
typedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLBINDPARAMETER )\
					( IN SQLHSTMT StatementHandle, 
					SQLUSMALLINT ParameterNumber, SQLSMALLINT InputOutputType,
					SQLSMALLINT ValueType, SQLSMALLINT ParameterType,
					SQLUINTEGER ColumnSize, SQLSMALLINT DecimalDigits,
					IN_BUFFER_OPT( BufferLength ) SQLPOINTER ParameterValuePtr, 
					SQLINTEGER BufferLength, 
					INOUT_OPT SQLINTEGER *StrLen_or_IndPtr );
typedef SQLRETURN ( SQL_API *SQLCLOSECURSOR )( IN SQLHSTMT StatementHandle );
typedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLCONNECT )\
					( IN SQLHDBC ConnectionHandle,
					IN_BUFFER( NameLength1 ) SQLCHAR *ServerName, 
					SQLSMALLINT NameLength1,
					IN_BUFFER( NameLength2 ) SQLCHAR *UserName, 
					SQLSMALLINT NameLength2,
					IN_BUFFER( NameLength3 ) SQLCHAR *Authentication, 
					SQLSMALLINT NameLength3 );
typedef SQLRETURN ( SQL_API *SQLDISCONNECT )( IN SQLHDBC ConnectionHandle );
typedef SQLRETURN ( SQL_API *SQLENDTRAN )( SQLSMALLINT HandleType,
					IN SQLHANDLE Handle, SQLSMALLINT CompletionType );
typedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLEXECDIRECT )\
					( SQLHSTMT StatementHandle,
					IN_BUFFER( TextLength ) SQLCHAR *StatementText, 
					SQLINTEGER TextLength );
typedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLEXECUTE )\
					( IN SQLHSTMT StatementHandle );
typedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLFETCH )\
					( IN SQLHSTMT StatementHandle );
typedef SQLRETURN ( SQL_API *SQLFREEHANDLE )( SQLSMALLINT HandleType,
					IN SQLHANDLE Handle );
typedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLGETDATA )\
					( SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, 
					SQLSMALLINT TargetType, 
					OUT_BUFFER( BufferLength, *StrLen_or_IndPtr ) \
						SQLPOINTER TargetValuePtr, 
					SQLINTEGER BufferLength, SQLINTEGER *StrLen_or_IndPtr );
typedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLGETDIAGREC )\
					( SQLSMALLINT HandleType,
					IN SQLHANDLE Handle, SQLSMALLINT RecNumber,
					OUT_BUFFER_FIXED( SQL_SQLSTATE_SIZE ) SQLCHAR *Sqlstate, 
					OUT SQLINTEGER *NativeErrorPtr,
					OUT_BUFFER( BufferLength, *TextLengthPtr ) \
						SQLCHAR *MessageText, 
					SQLSMALLINT BufferLength, SQLSMALLINT *TextLengthPtr );
typedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLGETINFO )\
					( IN SQLHDBC ConnectionHandle,
					SQLUSMALLINT InfoType, 
					OUT_BUFFER( BufferLength, *StringLengthPtr ) \
						SQLPOINTER InfoValuePtr, 
					SQLSMALLINT BufferLength, SQLSMALLINT *StringLengthPtr );
typedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLGETSTMTATTR )\
					( IN SQLHSTMT StatementHandle,
					SQLINTEGER Attribute, OUT SQLPOINTER ValuePtr,
					SQLINTEGER BufferLength, 
					STDC_UNUSED SQLINTEGER *StringLengthPtr );
typedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLGETTYPEINFO )\
					( IN SQLHSTMT StatementHandle,
					SQLSMALLINT DataType );
typedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLPREPARE )\
					( IN SQLHSTMT StatementHandle,
					IN_BUFFER( TextLength ) SQLCHAR *StatementText, 
					SQLINTEGER TextLength );
typedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLROWCOUNT_FN )\
					( IN SQLHSTMT StatementHandle,
					OUT SQLINTEGER *RowCountPtr );
typedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLSETCONNECTATTR )\
					( IN SQLHDBC ConnectionHandle,
					SQLINTEGER Attribute, SQLPOINTER ValuePtr,
					SQLINTEGER StringLength );
typedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLSETENVATTR )\
					( IN SQLHENV EnvironmentHandle,
					SQLINTEGER Attribute, SQLPOINTER ValuePtr,
					SQLINTEGER StringLength );
typedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLSETSTMTATTR )\
					( IN SQLHSTMT StatementHandle,
					SQLINTEGER Attribute, SQLPOINTER ValuePtr,
					SQLINTEGER StringLength );

static SQLALLOCHANDLE pSQLAllocHandle = NULL;
static SQLBINDPARAMETER pSQLBindParameter = NULL;
static SQLCLOSECURSOR pSQLCloseCursor = NULL;
static SQLCONNECT pSQLConnect = NULL;
static SQLDISCONNECT pSQLDisconnect = NULL;
static SQLENDTRAN pSQLEndTran = NULL;
static SQLEXECDIRECT pSQLExecDirect = NULL;
static SQLEXECUTE pSQLExecute = NULL;
static SQLFETCH pSQLFetch = NULL;
static SQLFREEHANDLE pSQLFreeHandle = NULL;
static SQLGETDATA pSQLGetData = NULL;
static SQLGETDIAGREC pSQLGetDiagRec = NULL;
static SQLGETINFO pSQLGetInfo = NULL;
static SQLGETSTMTATTR pSQLGetStmtAttr = NULL;
static SQLGETTYPEINFO pSQLGetTypeInfo = NULL;
static SQLPREPARE pSQLPrepare = NULL;
static SQLROWCOUNT_FN pSQLRowCount = NULL;
static SQLSETCONNECTATTR pSQLSetConnectAttr = NULL;
static SQLSETENVATTR pSQLSetEnvAttr = NULL;
static SQLSETSTMTATTR pSQLSetStmtAttr = NULL;

/* The use of dynamically bound function pointers vs. statically linked
   functions requires a bit of sleight of hand since we can't give the
   pointers the same names as prototyped functions.  To get around this we
   redefine the actual function names to the names of the pointers */

#define SQLAllocHandle			pSQLAllocHandle
#define SQLBindParameter		pSQLBindParameter
#define SQLCloseCursor			pSQLCloseCursor
#define SQLConnect				pSQLConnect
#define SQLDisconnect			pSQLDisconnect
#define SQLEndTran				pSQLEndTran
#define SQLExecDirect			pSQLExecDirect
#define SQLExecute				pSQLExecute
#define SQLFetch				pSQLFetch
#define SQLFreeHandle			pSQLFreeHandle
#define SQLGetData				pSQLGetData
#define SQLGetDiagRec			pSQLGetDiagRec
#define SQLGetInfo				pSQLGetInfo
#define SQLGetStmtAttr			pSQLGetStmtAttr
#define SQLGetTypeInfo			pSQLGetTypeInfo
#define SQLPrepare				pSQLPrepare
#define SQLRowCount				pSQLRowCount
#define SQLSetConnectAttr		pSQLSetConnectAttr
#define SQLSetEnvAttr			pSQLSetEnvAttr
#define SQLSetStmtAttr			pSQLSetStmtAttr

/* Depending on whether we're running under Win16, Win32, or Unix we load the
   ODBC driver under a different name */

#if defined( __WIN16__ )
  #define ODBC_LIBNAME			"ODBC.DLL"
#elif defined( __WIN32__ )
  #define ODBC_LIBNAME			"ODBC32.DLL"
#elif defined( __UNIX__ )
  #if defined( __APPLE__ )
	/* OS X has built-in ODBC support via iODBC */
	#define ODBC_LIBNAME		"libiodbc.dylib"
  #else
	/* Currently we default to UnixODBC, which uses libodbc.so.  If this
	   fails, we fall back to the next-most-common one, iODBC.  If you're
	   using something else, you'll need to change the entry below to
	   specify your library name */
	#define ODBC_LIBNAME		"libodbc.so"
	#define ODBC_ALT_LIBNAME	"libiodbc.so"
  #endif /* Mac OS X vs. other Unixen */
#endif /* System-specific ODBC library names */

/* Dynamically load and unload any necessary DBMS libraries */

CHECK_RETVAL \
int dbxInitODBC( void )
	{
#ifdef __WIN16__
	UINT errorMode;
#endif /* __WIN16__ */

	/* If the ODBC module is already linked in, don't do anything */
	if( hODBC != NULL_INSTANCE )
		return( CRYPT_OK );

	/* Obtain a handle to the module containing the ODBC functions */
#if defined( __WIN16__ )
	errorMode = SetErrorMode( SEM_NOOPENFILEERRORBOX );
	hODBC = LoadLibrary( ODBC_LIBNAME );
	SetErrorMode( errorMode );
	if( hODBC < HINSTANCE_ERROR )
		{
		hODBC = NULL_INSTANCE;
		return( CRYPT_ERROR );
		}
#elif defined( __UNIX__ ) && !defined( __APPLE__ )
	if( ( hODBC = DynamicLoad( ODBC_LIBNAME ) ) == NULL_INSTANCE && \
		( hODBC = DynamicLoad( ODBC_ALT_LIBNAME ) ) == NULL_INSTANCE )
		return( CRYPT_ERROR );
#else
	if( ( hODBC = DynamicLoad( ODBC_LIBNAME ) ) == NULL_INSTANCE )
		return( CRYPT_ERROR );
#endif /* __WIN32__ */

	/* Now get pointers to the functions */
	pSQLAllocHandle = ( SQLALLOCHANDLE ) DynamicBind( hODBC, "SQLAllocHandle" );
	pSQLBindParameter = ( SQLBINDPARAMETER ) DynamicBind( hODBC, "SQLBindParameter" );
	pSQLCloseCursor = ( SQLCLOSECURSOR ) DynamicBind( hODBC, "SQLCloseCursor" );
	pSQLConnect = ( SQLCONNECT ) DynamicBind( hODBC, "SQLConnect" );
	pSQLDisconnect = ( SQLDISCONNECT ) DynamicBind( hODBC, "SQLDisconnect" );
	pSQLEndTran = ( SQLENDTRAN ) DynamicBind( hODBC, "SQLEndTran" );
	pSQLExecDirect = ( SQLEXECDIRECT ) DynamicBind( hODBC, "SQLExecDirect" );
	pSQLExecute = ( SQLEXECUTE ) DynamicBind( hODBC, "SQLExecute" );
	pSQLFetch = ( SQLFETCH ) DynamicBind( hODBC, "SQLFetch" );
	pSQLFreeHandle = ( SQLFREEHANDLE ) DynamicBind( hODBC, "SQLFreeHandle" );
	pSQLGetData = ( SQLGETDATA ) DynamicBind( hODBC, "SQLGetData" );
	pSQLGetDiagRec = ( SQLGETDIAGREC ) DynamicBind( hODBC, "SQLGetDiagRec" );
	pSQLGetInfo = ( SQLGETINFO ) DynamicBind( hODBC, "SQLGetInfo" );
	pSQLGetStmtAttr = ( SQLGETSTMTATTR ) DynamicBind( hODBC, "SQLGetStmtAttr" );
	pSQLGetTypeInfo = ( SQLGETTYPEINFO ) DynamicBind( hODBC, "SQLGetTypeInfo" );
	pSQLPrepare = ( SQLPREPARE ) DynamicBind( hODBC, "SQLPrepare" );
	pSQLRowCount = ( SQLROWCOUNT_FN ) DynamicBind( hODBC, "SQLRowCount" );
	pSQLSetConnectAttr = ( SQLSETCONNECTATTR ) DynamicBind( hODBC, "SQLSetConnectAttr" );
	pSQLSetEnvAttr = ( SQLSETENVATTR ) DynamicBind( hODBC, "SQLSetEnvAttr" );
	pSQLSetStmtAttr = ( SQLSETSTMTATTR ) DynamicBind( hODBC, "SQLSetStmtAttr" );

	/* Make sure that we got valid pointers for every ODBC function */
	if( pSQLAllocHandle == NULL || pSQLBindParameter == NULL ||
		pSQLCloseCursor == NULL || pSQLConnect == NULL ||
		pSQLDisconnect == NULL || pSQLEndTran == NULL ||
		pSQLExecDirect == NULL || pSQLExecute == NULL ||
		pSQLFetch == NULL || pSQLFreeHandle == NULL ||
		pSQLGetData == NULL || pSQLGetDiagRec == NULL ||
		pSQLGetInfo == NULL || pSQLGetStmtAttr == NULL ||
		pSQLGetTypeInfo == NULL || pSQLPrepare == NULL || 
		pSQLSetConnectAttr == NULL || pSQLSetEnvAttr == NULL || 
		pSQLSetStmtAttr == NULL )
		{
		/* Free the library reference and reset the handle */
		DynamicUnload( hODBC );
		hODBC = NULL_INSTANCE;
		return( CRYPT_ERROR );
		}

	return( CRYPT_OK );
	}

void dbxEndODBC( void )
	{
	if( hODBC != NULL_INSTANCE )
		DynamicUnload( hODBC );
	hODBC = NULL_INSTANCE;
	}
#else

CHECK_RETVAL \
int dbxInitODBC( void )
	{
	return( CRYPT_OK );
	}

void dbxEndODBC( void )
	{
	}
#endif /* DYNAMIC_LOAD */

/****************************************************************************
*																			*
*						 		Utility Routines							*
*																			*
****************************************************************************/

/* Get information on an ODBC error.  The statement handle is specified as a
   distinct parameter because it may be an ephemeral handle not part of the
   state information data */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int getErrorInfo( INOUT DBMS_STATE_INFO *dbmsInfo, 
						 IN_ENUM( SQL_ERRLVL ) const SQL_ERRLVL_TYPE errorLevel, 
						 const SQLHSTMT hStmt, 
						 IN_ERROR const int defaultStatus )
	{
	ERROR_INFO *errorInfo = &dbmsInfo->errorInfo;
	char szSqlState[ SQL_SQLSTATE_SIZE + 8 ];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -