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

📄 odbc.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 4 页
字号:
/****************************************************************************
*																			*
*						 cryptlib ODBC Mapping Routines						*
*						Copyright Peter Gutmann 1996-2004					*
*																			*
****************************************************************************/

#include <stdio.h>
#include <string.h>
#if defined( INC_ALL )
  #include "crypt.h"
  #include "keyset.h"
  #include "dbms.h"
#elif defined( INC_CHILD )
  #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 */

/* The following code can be run under any version of ODBC from 1.x to 3.x,
   although it assumes that a 3.x-level SDK is being used.  This is fairly
   likely, since this has been around since mid-1995.  If a pre-3.0 SDK is
   being used, then the following mappings will need to be applied:

	SQL_C_SLONG -> SQL_C_LONG
	SQLCHAR -> UCHAR
	SQLHANDLE -> Generic HENV/HSTMT/HDBC
	SQLHDBC -> HDBC
	SQLHENV -> HENV
	SQLHSTMT -> HSTMT
	SQLINTEGER -> SDWORD
	SQLPOINTER -> PTR
	SQLRETURN -> RETCODE
	SQLSMALLINT - SWORD
	SQLUINTEGER -> UDWORD
	SQLUSMALLINT -> UWORD

   Note that this can't be done automatically because the values are
   typedefs rather than #defines, which can't be detected at compile time.
   In addition under Windows the ODBC1x define needs to be used to enable
   the mapping of ODBC 1.x functions */

/* The ODBC 1.x SQLError() function returns error information at various
   levels and is rather unstable in its handling of input parameters, for
   example with some Win16 drivers if you pass it a valid hStmt then it may
   GPF after some calls so you need to force a NULL hStmt.  The following
   values define the levels of handle that we pass in in order for the ODBC
   1.x SQLError() to work as advertised.

   For ODBC 3.x only a single handle is used for SQLDiagRec(), but we still
   need these codes to indicate the type of the handle that's being passed */

#define SQL_ERRLVL_STMT	0
#define SQL_ERRLVL_DBC	1
#define SQL_ERRLVL_ENV	2

/* 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 )

#ifdef USE_ODBC

/****************************************************************************
*																			*
*						 		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
   DLL/shared libs's.  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 this particular function is typedef'd with a _FN suffix
   to reduce problems */

static INSTANCE_HANDLE hODBC = NULL_INSTANCE;

typedef SQLRETURN ( SQL_API *SQLALLOCHANDLE )( SQLSMALLINT HandleType,
					SQLHANDLE InputHandle, SQLHANDLE *OutputHandlePtr );
typedef SQLRETURN ( SQL_API *SQLBINDPARAMETER )( SQLHSTMT StatementHandle,
					SQLUSMALLINT ParameterNumber, SQLSMALLINT InputOutputType,
					SQLSMALLINT ValueType, SQLSMALLINT ParameterType,
					SQLUINTEGER ColumnSize, SQLSMALLINT DecimalDigits,
					SQLPOINTER ParameterValuePtr, SQLINTEGER BufferLength,
					SQLINTEGER *StrLen_or_IndPtr );
typedef SQLRETURN ( SQL_API *SQLCLOSECURSOR )( SQLHSTMT StatementHandle );
typedef SQLRETURN ( SQL_API *SQLCONNECT )( SQLHDBC ConnectionHandle,
					SQLCHAR *ServerName, SQLSMALLINT NameLength1,
					SQLCHAR *UserName, SQLSMALLINT NameLength2,
					SQLCHAR *Authentication, SQLSMALLINT NameLength3 );
typedef SQLRETURN ( SQL_API *SQLDISCONNECT )( SQLHDBC ConnectionHandle );
typedef SQLRETURN ( SQL_API *SQLENDTRAN )( SQLSMALLINT HandleType,
					SQLHANDLE Handle, SQLSMALLINT CompletionType );
typedef SQLRETURN ( SQL_API *SQLEXECDIRECT )( SQLHSTMT StatementHandle,
					SQLCHAR *StatementText, SQLINTEGER TextLength );
typedef SQLRETURN ( SQL_API *SQLEXECUTE )( SQLHSTMT StatementHandle );
typedef SQLRETURN ( SQL_API *SQLFETCH )( SQLHSTMT StatementHandle );
typedef SQLRETURN ( SQL_API *SQLFREEHANDLE )( SQLSMALLINT HandleType,
					SQLHANDLE Handle );
typedef SQLRETURN ( SQL_API *SQLGETDATA )( SQLHSTMT StatementHandle,
					SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType,
					SQLPOINTER TargetValuePtr, SQLINTEGER BufferLength,
					SQLINTEGER *StrLen_or_IndPtr );
typedef SQLRETURN ( SQL_API *SQLGETDIAGREC )( SQLSMALLINT HandleType,
					SQLHANDLE Handle, SQLSMALLINT RecNumber,
					SQLCHAR *Sqlstate, SQLINTEGER *NativeErrorPtr,
					SQLCHAR *MessageText, SQLSMALLINT BufferLength,
					SQLSMALLINT *TextLengthPtr );
typedef SQLRETURN ( SQL_API *SQLGETINFO )( SQLHDBC ConnectionHandle,
					SQLUSMALLINT InfoType, SQLPOINTER InfoValuePtr,
					SQLSMALLINT BufferLength, SQLSMALLINT *StringLengthPtr );
typedef SQLRETURN ( SQL_API *SQLGETSTMTATTR )( SQLHSTMT StatementHandle,
					SQLINTEGER Attribute, SQLPOINTER ValuePtr,
					SQLINTEGER BufferLength, SQLINTEGER *StringLengthPtr );
typedef SQLRETURN ( SQL_API *SQLGETTYPEINFO )( SQLHSTMT StatementHandle,
					SQLSMALLINT DataType );
typedef SQLRETURN ( SQL_API *SQLPARAMDATA )( SQLHSTMT StatementHandle,
					SQLPOINTER *ValuePtrPtr );
typedef SQLRETURN ( SQL_API *SQLPREPARE )( SQLHSTMT StatementHandle,
					SQLCHAR *StatementText, SQLINTEGER TextLength );
typedef SQLRETURN ( SQL_API *SQLPUTDATA )( SQLHSTMT StatementHandle,
					SQLPOINTER DataPtr, SQLINTEGER StrLen_or_Ind );
typedef SQLRETURN ( SQL_API *SQLROWCOUNT_FN )( SQLHSTMT StatementHandle,
					SQLINTEGER *RowCountPtr );
typedef SQLRETURN ( SQL_API *SQLSETCONNECTATTR )( SQLHDBC ConnectionHandle,
					SQLINTEGER Attribute, SQLPOINTER ValuePtr,
					SQLINTEGER StringLength );
typedef SQLRETURN ( SQL_API *SQLSETENVATTR )( SQLHENV EnvironmentHandle,
					SQLINTEGER Attribute, SQLPOINTER ValuePtr,
					SQLINTEGER StringLength );
typedef SQLRETURN ( SQL_API *SQLSETSTMTATTR )( SQLHSTMT StatementHandle,
					SQLINTEGER Attribute, SQLPOINTER ValuePtr,
					SQLINTEGER StringLength );
#ifdef ODBC1x
typedef SQLRETURN ( SQL_API *SQLALLOCENV )( SQLHENV *phEnv );
typedef SQLRETURN ( SQL_API *SQLALLOCCONNECT )( SQLHENV hEnv,
					SQLHDBC *phDbc );
typedef SQLRETURN ( SQL_API *SQLALLOCSTMT )( SQLHDBC hDbc,
					SQLHSTMT *phStmt );
typedef SQLRETURN ( SQL_API *SQLERROR )( SQLHENV henv, SQLHDBC hDbc,
					SQLHSTMT hStmt, SQLCHAR *szSqlState,
					SQLINTEGER *pfNativeError, SQLCHAR *szErrorMsg,
					SQLSMALLINT cbErrorMsgMax, SQLSMALLINT *pcbErrorMsg );
typedef SQLRETURN ( SQL_API *SQLFREECONNECT )( SQLHDBC hDbc );
typedef SQLRETURN ( SQL_API *SQLFREEENV )( SQLHENV hEnv );
typedef SQLRETURN ( SQL_API *SQLFREESTMT )( SQLHSTMT hStmt, SQLUSMALLINT fOption );
typedef SQLRETURN ( SQL_API *SQLSETCONNECTOPTION )( SQLHDBC hdbc, UWORD fOption,
					UDWORD vParam );
typedef SQLRETURN ( SQL_API *SQLSETSTMTOPTION )( SQLHSTMT hstmt, UWORD fOption,
				  UDWORD vParam );
typedef SQLRETURN ( SQL_API *SQLTRANSACT )( SQLHENV hEnv, SQLHDBC hDbc, SQLUSMALLINT fType );
#endif /* ODBC1x */

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 SQLPARAMDATA pSQLParamData = NULL;
static SQLPREPARE pSQLPrepare = NULL;
static SQLPUTDATA pSQLPutData = NULL;
static SQLROWCOUNT_FN pSQLRowCount = NULL;
static SQLSETCONNECTATTR pSQLSetConnectAttr = NULL;
static SQLSETENVATTR pSQLSetEnvAttr = NULL;
static SQLSETSTMTATTR pSQLSetStmtAttr = NULL;

#ifdef ODBC1x
static SQLALLOCCONNECT pSQLAllocConnect = NULL;
static SQLALLOCENV pSQLAllocEnv = NULL;
static SQLALLOCSTMT pSQLAllocStmt = NULL;
static SQLERROR pSQLError = NULL;
static SQLFREECONNECT pSQLFreeConnect = NULL;
static SQLFREEENV pSQLFreeEnv = NULL;
static SQLFREESTMT pSQLFreeStmt = NULL;
static SQLSETCONNECTOPTION pSQLSetConnectOption = NULL;
static SQLSETSTMTOPTION pSQLSetStmtOption = NULL;
static SQLTRANSACT pSQLTransact = NULL;
#endif /* ODBC1x */

/* 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 SQLParamData			pSQLParamData
#define SQLPrepare				pSQLPrepare
#define SQLPutData				pSQLPutData
#define SQLRowCount				pSQLRowCount
#define SQLSetConnectAttr		pSQLSetConnectAttr
#define SQLSetEnvAttr			pSQLSetEnvAttr
#define SQLSetStmtAttr			pSQLSetStmtAttr

#ifdef ODBC1x
#define SQLAllocConnect			pSQLAllocConnect
#define SQLAllocEnv				pSQLAllocEnv
#define SQLAllocStmt			pSQLAllocStmt
#define SQLError				pSQLError
#define SQLFreeConnect			pSQLFreeConnect
#define SQLFreeEnv				pSQLFreeEnv
#define SQLFreeStmt				pSQLFreeStmt
#define SQLSetConnectOption		pSQLSetConnectOption
#define SQLSetStmtOption		pSQLSetStmtOption
#define SQLTransact				pSQLTransact
#endif /* ODBC1x */

/* 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
	#define ODBC_LIBNAME  "libodbc.so"
  #endif /* Mac OS X vs. other Unixen */
#endif /* System-specific ODBC library names */

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

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 */
#ifdef __WIN16__
	errorMode = SetErrorMode( SEM_NOOPENFILEERRORBOX );
	hODBC = LoadLibrary( ODBC_LIBNAME );
	SetErrorMode( errorMode );
	if( hODBC < HINSTANCE_ERROR )
		{
		hODBC = 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" );
	pSQLParamData = ( SQLPARAMDATA ) DynamicBind( hODBC, "SQLParamData" );
	pSQLPrepare = ( SQLPREPARE ) DynamicBind( hODBC, "SQLPrepare" );
	pSQLPutData = ( SQLPUTDATA ) DynamicBind( hODBC, "SQLPutData" );
	pSQLRowCount = ( SQLROWCOUNT_FN ) DynamicBind( hODBC, "SQLRowCount" );
	pSQLSetConnectAttr = ( SQLSETCONNECTATTR ) DynamicBind( hODBC, "SQLSetConnectAttr" );
	pSQLSetEnvAttr = ( SQLSETENVATTR ) DynamicBind( hODBC, "SQLSetEnvAttr" );
	pSQLSetStmtAttr = ( SQLSETSTMTATTR ) DynamicBind( hODBC, "SQLSetStmtAttr" );

#ifdef ODBC1x
	pSQLAllocConnect = ( SQLALLOCCONNECT ) DynamicBind( hODBC, "SQLAllocConnect" );
	pSQLAllocEnv = ( SQLALLOCENV ) DynamicBind( hODBC, "SQLAllocEnv" );
	pSQLAllocStmt = ( SQLALLOCSTMT ) DynamicBind( hODBC, "SQLAllocStmt" );
	pSQLError = ( SQLERROR ) DynamicBind( hODBC, "SQLError" );
	pSQLFreeConnect = ( SQLFREECONNECT ) DynamicBind( hODBC, "SQLFreeConnect" );
	pSQLFreeEnv = ( SQLFREEENV ) DynamicBind( hODBC, "SQLFreeEnv" );
	pSQLFreeStmt = ( SQLFREESTMT ) DynamicBind( hODBC, "SQLFreeStmt" );
	pSQLSetConnectOption = ( SQLSETCONNECTOPTION ) DynamicBind( hODBC, "SQLSetConnectOption" );
	pSQLSetStmtOption = ( SQLSETSTMTOPTION ) DynamicBind( hODBC, "SQLSetStmtOption" );
	pSQLTransact = ( SQLTRANSACT ) DynamicBind( hODBC, "SQLTransact" );
#endif /* ODBC1x */

	/* 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 || pSQLParamData == NULL ||
		pSQLPrepare == NULL || pSQLPutData == 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

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

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

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

⌨️ 快捷键说明

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