home *** CD-ROM | disk | FTP | other *** search
/ PC World 1998 December / PCWorld_1998-12_cd.iso / software / sybase / ASA / asa60.exe / data1.cab / src_files / esqldll.c
C/C++ Source or Header  |  1998-07-27  |  12KB  |  367 lines

  1.  /****************************************************************
  2.  *       Copyright (C) 1988-1998, by Sybase, Inc.                *
  3.  *       All rights reserved. No part of this software may be    *
  4.  *       reproduced in any form or by any means - graphic,       *
  5.  *       electronic or mechanical, including photocopying,       *
  6.  *       recording, taping or information storage and retrieval  *
  7.  *       systems - except with the written permission of         *
  8.  *       Sybase, Inc.                                            *
  9.  ****************************************************************/
  10.  
  11. /*
  12. Overview:
  13. ~~~~~~~~~
  14.  
  15.     By using this module with your embedded SQL application,
  16.     your application will be more robust in its ability to
  17.     locate the database interface DLL, and you will not need
  18.     to link against the import library for the DLL.
  19.  
  20. Usage:
  21. ~~~~~~
  22.  
  23. 1) Your program must call db_init_dll to load the DLL, and must
  24.    call db_fini_dll to free the DLL.  db_init_dll must be called
  25.    before any function in the database interface, and no function
  26.    in the interface can be called after db_fini_dll.
  27.    See below for more details on db_init_dll and db_fini_dll.
  28.  
  29.    Note that you must still call db_init and db_fini.
  30.  
  31. 2) You must #include the file esqldll.h before the
  32.    EXEC SQL INCLUDE SQLCA statement or #include <sqlca.h> line
  33.    in your embedded SQL program.
  34.  
  35. 3) You must ensure that a SQL OS macro is defined when compiling this file.
  36.    (esqldll.c>.  The header file sqlca.h, which is included by this file,
  37.    attempts to determine the appropriate macro and defines it.  However,
  38.    certain combinations of platforms and compilers may cause this to fail.
  39.    In this case, you must add a #define to the top of this file, or
  40.    make the definition by using a compiler option.
  41.  
  42.         Macro          Platforms
  43.     ~~~~~             ~~~~~~~~~
  44.        _SQL_OS_WINNT     32-bit Windows (NT, 95, Win32s)
  45.     _SQL_OS_WINDOWS   16-bit Windows (3.1, 3.11)
  46.     _SQL_OS_OS232     32-bit OS/2
  47.  
  48. 4) Compile this file.
  49.  
  50. 5) Instead of linking against the imports library, link the object
  51.    module "esqldll.obj" with your embedded SQL application objects.
  52. */
  53.  
  54. #define _NO_FUNC_INFO
  55. #include <stdio.h>
  56. #include <stdlib.h>
  57. #include <string.h>
  58. #include "sqlca.h"
  59. #include "sqldef.h"
  60. #include "esqldll.h"
  61.  
  62. #if defined( _SQL_OS_WINDOWS ) || defined( _SQL_OS_WINNT )
  63.     #include <windows.h>
  64. #elif defined ( _SQL_OS_OS232 )
  65.     #define INCL_DOSMODULEMGR
  66.     #include <os2.h>
  67. #endif
  68.  
  69.  
  70. /****************************************/
  71. /* declare & initialize version externs */
  72. /****************************************/
  73.  
  74. extern a_sqlpp_version_number    _ESQL_Version6_ = SQLPP_DBLIB_VERSION;
  75. extern a_sqlpp_version_number    _ESQL_Version4_ = 4;
  76.  
  77. #if defined( _SQL_OS_WINNT )
  78.     extern unsigned short _ESQL_OS_WINNT_ = SQLPP_DBLIB_VERSION;
  79.     #define _DLL_SUBDIR         "win32\\"
  80.     #define _WINNT_DLL_NAME     "dblib6.dll"
  81.     #define _WIN32s_DLL_NAME     "dblib6s.dll"
  82. #elif defined( _SQL_OS_WINDOWS )
  83.     extern unsigned short _ESQL_OS_WINDOWS_ = SQLPP_DBLIB_VERSION;
  84.     #define _DLL_SUBDIR        "win\\"
  85.     #define _DLL_NAME        "dblib6w.dll"
  86. #elif defined( _SQL_OS_OS232 )
  87.     extern unsigned short _ESQL_OS_OS232_ = SQLPP_DBLIB_VERSION;
  88.     #define _DLL_SUBDIR         "os2\\"
  89.     #define _DLL_NAME        "dblib6"    // don't include .dll in name
  90. #else
  91.     #error Dynamic DLL loading not supported under this OS.
  92. #endif
  93.  
  94.  
  95. /******************************/
  96. /* declare & initialize SQLCA */
  97. /******************************/
  98.  
  99. extern struct sqlca sqlca = {
  100.     "SQLCA   ",                     /* sqlcaid  */
  101.     sizeof( SQLCA ),                /* sqlabc   */
  102.     0L,                             /* sqlcode */
  103.     0,                              /* sqlerrml */
  104.     "",                             /* sqlerrmc */
  105.     { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' },    /* sqlerrp  */
  106.     {0L, 0L, 0L, 0L, 0L, 0L},       /* sqlerrd */
  107.     {0},                            /* sqlwarn  */
  108.     {0,0,0,0,0,0}                   /* sqlstate   */
  109. };
  110.  
  111. extern struct sqlca _fd_ *sqlcaptr = { &sqlca };
  112.  
  113.  
  114. /******************************/
  115. /* Declare function pointers  */
  116. /******************************/
  117.  
  118. #define FUNC_INFO( scope, rettype, call, fname, parms ) \
  119.     rettype ( call _fd_ * fname ) parms;
  120. #include "sqlfuncs.h"
  121. #undef FUNC_INFO
  122.  
  123. /********************************/
  124. /* Open DLL and assign pointers */
  125. /********************************/
  126.  
  127. #if defined( _SQL_OS_WINNT ) || defined( _SQL_OS_OS232 )
  128.     static HMODULE dll_handle;
  129. #elif defined( _SQL_OS_WINDOWS )
  130.     static HINSTANCE dll_handle;
  131. #endif
  132.  
  133.  
  134. /********************************************************/
  135. /* Functions for opening/closing database interface DLL */
  136. /********************************************************/
  137.  
  138. #define _SQL_REGISTRY_KEY    "Software\\Sybase\\Adaptive Server Anywhere\\6.0"
  139. #define _SQL_REGISTRY_FIELD     "Location"
  140. #define _SQL_INI_FILE        "asany.ini"
  141. #define _SQL_INI_SECTION    "6.0"
  142. #define _SQL_INI_KEY        "Location"
  143.  
  144.  
  145. extern unsigned short db_fini_dll( void )
  146. /*
  147. ** This function unloads the DLL from the application.
  148. ** It returns zero if unsuccessful and zero if successful.
  149. */
  150. {
  151.     #if defined( _SQL_OS_WINNT )
  152.     return( FreeLibrary( dll_handle ) );
  153.     #elif defined( _SQL_OS_WINDOWS )
  154.     FreeLibrary( dll_handle );
  155.     return( TRUE );
  156.     #elif defined( _SQL_OS_OS232 )
  157.     return( DosFreeModule( dll_handle ) );
  158.     #endif
  159. }
  160.  
  161.  
  162. static unsigned short i_load_dll( char *path, int *wrongversion )
  163. /*
  164. ** This function attemps to load the DLL.  The path
  165. ** parameter should be a fully qualified path.
  166. ** If it loads successfully the function pointers
  167. ** are assigned and the version of the DLL is checked.
  168. */
  169. {
  170.     #if defined( _SQL_OS_OS232 )
  171.     long        result;
  172.     char        loaderror[100];
  173.     #endif
  174.  
  175.     #if defined( _SQL_OS_WINNT )
  176.     dll_handle = LoadLibrary( path );
  177.     if( dll_handle == NULL ) {
  178.         return( FALSE );
  179.     }
  180.     #elif defined( _SQL_OS_WINDOWS )
  181.     dll_handle = LoadLibrary( path );
  182.     if( dll_handle < HINSTANCE_ERROR ) {
  183.         return( FALSE );
  184.     }
  185.     #elif defined( _SQL_OS_OS232 )
  186.     result = DosLoadModule( (PSZ) loaderror, sizeof( loaderror ), (PSZ) path, &dll_handle );
  187.     if( result != 0 ) {
  188.         return( FALSE );
  189.     }
  190.     #endif
  191.  
  192.     #if defined( _SQL_OS_WINDOWS ) || defined( _SQL_OS_WINNT )
  193.     #define FUNC_INFO( scope, rettype, call, fname, parms ) \
  194.     fname = ( void _fd_ * ) GetProcAddress( dll_handle, #fname );
  195.     #elif defined( _SQL_OS_OS232 )
  196.     #define FUNC_INFO( scope, rettype, call, fname, parms ) \
  197.     result = DosQueryProcAddr( dll_handle, 0, (PSZ) #fname, (PFN *) &fname );
  198.     #endif
  199.     #include "sqlfuncs.h"
  200.     #undef FUNC_INFO
  201.  
  202.     if( db_version_check == NULL || !db_version_check( SQLPP_DBLIB_VERSION ) ) {
  203.     db_fini_dll(); /* free the DLL if version doesn't match */
  204.     *wrongversion = TRUE;
  205.         return( FALSE );
  206.     } else {
  207.     return( TRUE );
  208.     }
  209. }
  210.  
  211.  
  212. static void i_get_dll_name( char *path, int subdir )
  213. /*
  214. ** If subdir = TRUE, this function appends a subdirectory
  215. ** and dllname to path.
  216. ** If subdir = FALSE, this function only appends the dllname
  217. ** to path.
  218. ** The subdirectory and dllname are appropriate for the
  219. ** specified platform.
  220. */
  221. {
  222.     int            len;
  223.     #if defined( _SQL_OS_WINNT )
  224.     OSVERSIONINFO       osinfo;
  225.     #endif
  226.  
  227.     /* Ensure there is a trailing slash */
  228.     len = strlen( path );
  229.     if( len > 0 && path[ len - 1 ] != '\\' ) {
  230.     path[ len ] = '\\';
  231.     path[ len + 1 ] = '\0';
  232.     }
  233.  
  234.     if( subdir ) {
  235.     strcat( path, _DLL_SUBDIR );
  236.     }
  237.  
  238.     #if defined( _SQL_OS_WINNT )
  239.     /* Check if we are running under win32s */
  240.     osinfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
  241.     GetVersionEx( &osinfo );
  242.     if( osinfo.dwPlatformId == VER_PLATFORM_WIN32s ) {
  243.         strcat( path, _WIN32s_DLL_NAME );
  244.     } else {
  245.         strcat( path, _WINNT_DLL_NAME );
  246.     }
  247.     #else
  248.     strcat( path, _DLL_NAME ); 
  249.     #endif
  250. }
  251.  
  252.  
  253. #if defined( _SQL_OS_WINNT )
  254. static unsigned short AccessRegistry( HKEY hive, unsigned char *dllname )
  255. {
  256.     long        result;
  257.     HKEY        key;
  258.     DWORD        length;
  259.  
  260.     result = RegOpenKeyEx( hive, _SQL_REGISTRY_KEY, 0L, KEY_ALL_ACCESS, &key );
  261.     if( result == ERROR_SUCCESS ) {
  262.     length = _MAX_PATH;
  263.     result = RegQueryValueEx( key, _SQL_REGISTRY_FIELD, NULL, NULL, dllname, &length );
  264.     RegCloseKey( key );
  265.     }
  266.     return( result == ERROR_SUCCESS );
  267. }
  268. #endif
  269.  
  270.  
  271. extern unsigned short db_init_dll( char    **paths )
  272. /*
  273. ** This function uses a list of paths to the Adaptive Server Anywhere directory
  274. ** to try to load the database interface DLL.  If the DLL cannot be
  275. ** found in any of these paths, then it looks for the location of the SQL
  276. ** Anywhere installation in the registry to locate the DLL (only under NT
  277. ** or 95).  If that fails, it checks the environment variable for the
  278. ** location of the installation.  If that fails, it lets the OS search
  279. ** the PATH for the DLL.
  280. **
  281. ** The list of paths is passed as a pointer to an array of char pointers.
  282. ** The last pointer in the array must be NULL to signal the
  283. ** end of the array.
  284. ** Note that the dll filename will be appended to this path.
  285. ** For example, if you pass in the path
  286. ** "c:\asa60" and compile for WINNT, the function will look for
  287. ** "c:\asa60\dblib6.dll".
  288. **
  289. ** This function must be called before any other database
  290. ** interface function is called.
  291. **
  292. ** Note: If you are linking the database interface import library
  293. ** with your application then you should not call this function.
  294. **
  295. ** Return values:  (these macros are defined in sqldef.h)
  296. **      ESQLDLL_OK - dll was loaded and successfully
  297. **      ESQLDLL_DLL_NOT_FOUND - no DLL was located in any of the paths
  298. **      ESQLDLL_WRONG_VERSION - at least one copy of the DLL was located,
  299. **                              but all of them were the wrong version.
  300. */
  301. {
  302.     int            gotdll = FALSE;
  303.     int            wrongversion = FALSE;
  304.     int            n;
  305.     char        dllname[_MAX_PATH];
  306.     
  307.     if( paths != NULL ) {
  308.         for( n = 0; paths[n] != NULL && !gotdll; n++ ) {
  309.         strcpy( dllname, paths[n] );
  310.         i_get_dll_name( dllname, FALSE );
  311.         gotdll = i_load_dll( dllname, &wrongversion );
  312.         }
  313.     }
  314.  
  315.     #if defined( _SQL_OS_WINNT )
  316.     /* Look up the Adaptive Server Anywhere path in the registry */
  317.     if( !gotdll ) {
  318.     if( AccessRegistry( HKEY_CURRENT_USER, (unsigned char *) dllname )
  319.         || AccessRegistry( HKEY_LOCAL_MACHINE, (unsigned char *) dllname ) ) {
  320.         i_get_dll_name( dllname, TRUE );
  321.         gotdll = i_load_dll( dllname, &wrongversion );
  322.     }
  323.     }
  324.     #elif defined( _SQL_OS_WINDOWS )
  325.     /* Look up the Adaptive Server Anywhere path in the .ini file */
  326.     if( !gotdll ) {
  327.     if( GetPrivateProfileString( _SQL_INI_SECTION, _SQL_INI_KEY, "",
  328.         dllname, _MAX_PATH, _SQL_INI_FILE ) != 0 ) {
  329.         i_get_dll_name( dllname, TRUE );
  330.         gotdll = i_load_dll( dllname, &wrongversion );
  331.     }
  332.     }
  333.  
  334.     #endif
  335.  
  336.     if( !gotdll ) {  /* let the OS look for the DLL in the PATH */
  337.     dllname[0] = '\0';
  338.     i_get_dll_name( dllname, FALSE );
  339.     gotdll = i_load_dll( dllname, &wrongversion );
  340.     }
  341.  
  342.     if( gotdll ) {
  343.     return( ESQLDLL_OK );
  344.     }
  345.     if( wrongversion ) {
  346.     return( ESQLDLL_WRONG_VERSION );
  347.     }
  348.     return( ESQLDLL_DLL_NOT_FOUND );
  349. }
  350.  
  351.  
  352.  
  353. /*
  354. ** This function returns the HINSTANCE of the DBLib routine.  This is
  355. ** required because some routines (in Sybase Central for example) make
  356. ** calls directly out of the dblib dll and consequently must dynamically
  357. ** find those routines (which requires the HINSTANCE).
  358. **
  359. ** Returns
  360. **    HMODULE/HINSTANCE    the hinstance of the dblib dll
  361. */
  362.  
  363. extern void *db_get_dblib_dll( void )
  364. {
  365.     return (void *)dll_handle;
  366. }
  367.