ID: Q168052
The information in this article applies to:
There have been several changes to the Open Database Connectivity (ODBC) installation process from version 2.5 to version 3.0. SQLInstallDriver and SQLInstallODBC have been removed, and SQLInstallTranslator has been deprecated. These changes have made the Odbc.inf file unnecessary. The APIs below request data from, insert data, and make changes to the registry and the Odbc.ini and Odbcinst.ini files.
NOTE: These APIs do not copy files or perform any version checking of the drivers or driver manager. The source code included with this article has an example of how to perform the version checking and file copying, but is outside the scope of ODBC.
The following are the ODBC Core Components:
Ds16gt.dll
Ds32gt.dll
Odbccp32.dll
Odbc32.dll
Odbcad32.exe
Odbccr32.dll
Odbccp32.cpl
Odbctrac.dll
Odbcint.dll
Odbcinst.cnt
Odbcinst.hlp
Mtxdm.dll (if you use connection pooling)
My Datasource\0Server=bottles\0Database=\0;UID=sa\0
PWD=\0UseProcForPrepare=Yes\0Trusted_Connection=\0AnsiNPW=Yes\0\0
You can find detailed documentation for each of these functions in the
"ODBC 3.0 Programmers Reference, Volume 1, and SDK Guide".
The following C program illustrates a minimal application's set of requirements for installing the driver manager and a driver.
#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <odbcinst.h>
#include <winver.h>
#include <string.h>
#include <stdio.h>
#include <malloc.h>
#include "main.h"
#define DriverName "Bogus Driver"
#define DataSourceName "My Bogus Datasource"
#define DriverDLL "mysql32.dll"
void main()
{
if( ! Install() )
printf( "ODBC Install Failed\n" );
printf( "The End" );
}
/* General error handler for installer functions. */
BOOL ProcessErrorMessages( char * func )
{
WORD iError = 1;
DWORD pfErrorCode;
char lpszErrorMsg[301];
WORD cbErrorMsgMax = 300;
WORD pcbErrorMsg;
int rc;
BOOL func_rc = FALSE;
do
{
lpszErrorMsg[0] = '\0';
rc = SQLInstallerError(
iError,
& pfErrorCode,
lpszErrorMsg,
cbErrorMsgMax,
& pcbErrorMsg );
if( rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO )
{
printf( "%s in function %s", lpszErrorMsg, func );
func_rc = TRUE;
}
iError++;
}
while( rc != SQL_NO_DATA );
return func_rc;
}
BOOL Install() {
char szPath[301];
WORD cbPathMax = 300;
WORD cbPathOut;
BOOL rc;
UINT uVersionLength = 512;
/* First, retrieve the path the driver should be installed to in
szPath*/
if( SQLInstallDriverManager( szPath, cbPathMax, & cbPathOut ) )
{
/* Now compare the version of the core component files
and copy them if appropriate.
NOTE: For the purposes of this sample code. only Odbc32.dll is
being copied. */
if( VersionCheckCopyFile( szPath, "C:\\TEMP\\ODBC", "ODBC32.DLL" ) )
{
/* Check to see if the driver is already installed. */
if( rc = IsMyDriverInstalled() )
/* If the driver is already installed,
increase the usage count and return. */
BumpUpDriverUsageCount();
else
/* If not, install the driver. */
rc = InstallMyDriver();
if( rc )
/* After the driver is installed, create
the new DSN. */
AddMyDSN();
}
else
{
ProcessErrorMessages( "SQLInstallDriverManager" );
return FALSE;
}
}
else
{
ProcessErrorMessages( "SQLInstallDriverManager" );
return FALSE;
}
return TRUE;
}
BOOL IsMyDriverInstalled() {
char szBuf[2001];
WORD cbBufMax = 2000;
WORD cbBufOut;
char * pszBuf = szBuf;
/* Call SQLGetInstalledDrivers to retrieve an array with the
names of the installed drivers. */
if( SQLGetInstalledDrivers(
szBuf,
cbBufMax,
& cbBufOut) )
if( ProcessErrorMessages( "SQLGetInstalledDrivers" ) )
return FALSE;
/* Now loop through the array and search for the driver
being installed. */
do
{
if( strcmp( DriverName, pszBuf ) == 0 )
return TRUE;
pszBuf = strchr( pszBuf, '\0' ) + 1;
}
while( pszBuf[1] != '\0' );
return FALSE;
}
void BumpUpDriverUsageCount()
{
char szDriver[300];
char szPathIn[301];
char szPathOut[301];
WORD cbPathOutMax = 300;
WORD cbPathOut;
DWORD dwUsageCount;
/* The correct format of driver keywords are:
"DriverName\0Driver=MyDriver.DLL\0Setup=MySetup.DLL\0\0" */
/* Also, note that the driver's setup routines can be in the
same DLL. */
sprintf( szDriver, "Bogus
Driver\0Driver=mysql32.dll\0Setup=mysql32.dll\0\0" );
/* Inquire about the current usage count. */
SQLInstallDriverEx(
szDriver,
NULL,
szPathIn,
cbPathOutMax,
& cbPathOut,
ODBC_INSTALL_INQUIRY, /* this gets information about
the pre-existing driver */
& dwUsageCount );
/* Now increment the usage count. */
++dwUsageCount;
/* Then call SQLInstallDriverEx with the new usage count. */
if( ! SQLInstallDriverEx(
szDriver,
szPathIn,
szPathOut,
cbPathOutMax,
& cbPathOut,
ODBC_INSTALL_COMPLETE,
& dwUsageCount ) )
ProcessErrorMessages( "SQLInstallDriverEx" );
}
BOOL InstallMyDriver() {
char szDriver[300];
char szPathIn[301];
char szPathOut[301];
WORD cbPathOutMax = 300;
WORD cbPathOut;
DWORD dwUsageCount;
/* The correct format of driver keywords are:
"DriverName\0Driver=xxxxxx.DLL\0Setup=xxxxxx.DLL\0\0" */
sprintf( szDriver, "Bogus
Driver\0Driver=mysql32.dll\0Setup=mysql32.dll\0\0" );
/* The szDriver array is filled in before calling SQLInstallDriverEx
so that SQLInstallDriverEx will return where to install the driver in
the szPathIn */
SQLInstallDriverEx(
szDriver,
NULL,
szPathIn,
cbPathOutMax,
& cbPathOut,
ODBC_INSTALL_INQUIRY,
& dwUsageCount );
/* The correct format of driver keywords are:
"DriverName\0Driver=c:\winnt\system32\xxxxxx.DLL\0
Setup=c:\winnt\system32\xxxxxx.DLL\0\0" */
sprintf( szDriver,
"Bogus Driver\0Driver=%s\\mysql32.dll\0Setup=%s\\mysql32.dll\0\0",
szPathIn, szPathIn );
/* Compare the version of the driver and copy it if appropriate;
the following files are required for the SQL Server driver:
sqlsrv32_dll
dbnmpntw_dll
drvssrvr_hlp
instcat_sql
NOTE: For the purposes of this sample code, only Odbc32.dll is
being copied. */
if( ! VersionCheckCopyFile( szPathIn, "C:\\TEMP\\ODBC", DriverDLL ) )
if( ProcessErrorMessages( "SQLInstallDriverEx" ) )
return FALSE;
/* Call SQLInstallDriverEx to install the driver in
Odbcinst.ini and the registry. */
if( ! SQLInstallDriverEx(
szDriver,
szPathIn,
szPathOut,
cbPathOutMax,
& cbPathOut,
ODBC_INSTALL_COMPLETE,
& dwUsageCount ) )
if( ProcessErrorMessages( "SQLInstallDriverEx" ) )
return FALSE;
/* Call SQLConfigDriver to exercise the driver's setup
functions; some drivers have their setup routines built in,
and others require a seperate DLL */
SQLConfigDriver(
NULL,
ODBC_CONFIG_DRIVER,
DriverName,
"CPTimeout=60\0\0",
szPathOut,
cbPathOutMax,
& cbPathOut );
return TRUE;
}
BOOL AddMyDSN() {
char szDriver[300] = DriverName;
char szAttributes[400];
CreateAttributeString( szAttributes );
/* I choose to remove the DSN if it already existed */
SQLConfigDataSource(
NULL,
ODBC_REMOVE_SYS_DSN,
szDriver,
szAttributes );
/* then create a new DSN */
if( ! SQLConfigDataSource(
NULL,
ODBC_ADD_SYS_DSN,
szDriver,
szAttributes ) )
if( ProcessErrorMessages( "SQLConfigDataSource" ) )
return FALSE;
return TRUE;
}
/*************************************************************
/ This function builds the keyword pair string required by
/ SQLConfigDataSource.
/*************************************************************/
void CreateAttributeString( char * pszAttributes )
{
sprintf( pszAttributes,
"DSN=My Bogus DS\0Server=bottles\0Database=pubs\0UID=sa\0PWD=\0
UseProcForPrepare=yes\0\0" );
}
/* The following functions are not required for ODBC driver and driver
manager installation. They are for version checking and file copy of
DLLs; they require NO part of the ODBC API. */
BOOL GetFileVersion( char * pFilePath, char * pVersion, UINT uMaxVersionLen ) {
DWORD dwHandle = 0;
DWORD dwVersionInfoSize;
DWORD dwError;
PVOID pFileInfo;
PBYTE pVersionInfo;
PDWORD pTranslation = NULL;
UINT uLength = 0;
char szString[512] = "";
dwVersionInfoSize = GetFileVersionInfoSize(
pFilePath, /* pointer to filename string */
& dwHandle ); /* pointer to variable to receive zero */
if( ! dwVersionInfoSize )
{
dwError = GetLastError();
return FALSE;
}
pFileInfo = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
dwVersionInfoSize );
pVersionInfo = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
dwVersionInfoSize );
if( ! GetFileVersionInfo( pFilePath, /* pointer to filename string */
( DWORD ) dwHandle, /* ignored */
dwVersionInfoSize, /* size of buffer */
pFileInfo ) ) /* pointer to buffer to receive file-version info.*/
{
dwError = GetLastError();
HeapFree( GetProcessHeap(), 0, pFileInfo );
HeapFree( GetProcessHeap(), 0, pVersionInfo );
return FALSE;
}
if( ! VerQueryValue( pFileInfo, /* address of buffer for version
resource */
TEXT( "\\VarFileInfo\\Translation" ), /* address of value to retrieve
*/
& pTranslation, /* address of buffer for version pointer */
& uLength ) /* address of version-value length buffer */
)
{
dwError = GetLastError();
HeapFree( GetProcessHeap(), 0, pFileInfo );
HeapFree( GetProcessHeap(), 0, pVersionInfo );
return FALSE;
}
wsprintf( szString, "\\StringFileInfo\\%04x%04x\\FileVersion",
LOWORD( ( DWORD ) * pTranslation, ), HIWORD( ( DWORD ) * pTranslation
) );
if( ! VerQueryValue( pFileInfo, /* address of buffer for version
resource */
szString, /* address of value to retrieve */
( PVOID * ) & pVersionInfo, /* address of buffer for version
pointer */
& uLength ) /* address of version-value length buffer */
)
{
dwError = GetLastError();
HeapFree( GetProcessHeap(), 0, pFileInfo );
HeapFree( GetProcessHeap(), 0, pVersionInfo );
return FALSE;
}
if( lstrlen( pVersionInfo ) >= ( int ) uMaxVersionLen )
lstrcpyn( pVersion, pVersionInfo, uMaxVersionLen - 1 );
else
lstrcpy( pVersion, pVersionInfo );
HeapFree( GetProcessHeap(), 0, pFileInfo );
HeapFree( GetProcessHeap(), 0, pVersionInfo );
return TRUE;
}
BOOL CheckIfFileExists( char * szFilePath, char * szFileName ) {
DWORD nBufferLength = 300;
char szBuffer[300];
LPTSTR lpFilePart;
DWORD rt;
rt= SearchPath(
szFilePath, // address of search path
szFileName, // address of filename
NULL, //LPCTSTR lpExtension, // address of extension
nBufferLength, // size, in characters, of buffer
szBuffer, // address of buffer for found filename
& lpFilePart ); // address of pointer to file component
return rt;
}
/*********************************************************************
/ szOldPath is the "to path"
/ szNewPath is the "from path"
/ szFileName is the name of the file in the from path
/*********************************************************************/
BOOL VersionCheckCopyFile( char * szOldPath, char * szNewPath, char *
szFileName )
{
char szOldFile[512];
char szNewFile[512];
char szOldFileVersion[ 512 ];
char szNewFileVersion[ 512 ];
UINT uVersionLength = 512;
int rt;
if( CheckIfFileExists( szOldPath, szFileName ) )
{
sprintf( szOldFile, "%s\\%s", szOldPath, szFileName );
if( GetFileVersion( szOldFile, szOldFileVersion, uVersionLength ) )
{
sprintf( szNewFile, "%s\\%s", szNewPath, szFileName );
if( GetFileVersion( szNewFile, szNewFileVersion, uVersionLength )
)
{
rt = strcmp( szOldFileVersion, szNewFileVersion );
if( rt < 0 )
CopyFile( szNewFile, szOldFile, FALSE );
return TRUE;
}
else
return FALSE;
}
else
return FALSE;
}
else
{
sprintf( szOldFile, "%s\\%s", szOldPath, szFileName );
sprintf( szNewFile, "%s\\%s", szNewPath, szFileName );
CopyFile( szNewFile, szOldFile, FALSE );
}
return TRUE;
}
Additional query words: upgrade update
Keywords : kbcode kbprg SSrvProg odbcAPI
Version : 3.0
Platform : WINDOWS
Issue type : kbinfo
Last Reviewed: April 11, 1998