first commit for openGauss connect odbc code
This commit is contained in:
286
loadlib.c
Normal file
286
loadlib.c
Normal file
@ -0,0 +1,286 @@
|
||||
/*------
|
||||
* Module: loadlib.c
|
||||
*
|
||||
* Description: This module contains routines related to
|
||||
* delay load import libraries.
|
||||
*
|
||||
* Comments: See "readme.txt" for copyright and license information.
|
||||
*-------
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#ifndef WIN32
|
||||
#include <errno.h>
|
||||
#endif /* WIN32 */
|
||||
|
||||
#include "loadlib.h"
|
||||
#include "pgenlist.h"
|
||||
#include "misc.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "Delayimp")
|
||||
#ifdef _HANDLE_ENLIST_IN_DTC_
|
||||
#ifdef UNICODE_SUPPORT
|
||||
#pragma comment(lib, "pgenlist")
|
||||
#else
|
||||
#pragma comment(lib, "pgenlista")
|
||||
#endif /* UNICODE_SUPPORT */
|
||||
#endif /* _HANDLE_ENLIST_IN_DTC_ */
|
||||
// The followings works under VC++6.0 but doesn't work under VC++7.0.
|
||||
// Please add the equivalent linker options using command line etc.
|
||||
#if (_MSC_VER == 1200) && defined(DYNAMIC_LOAD) // VC6.0
|
||||
#ifdef UNICODE_SUPPORT
|
||||
#pragma comment(linker, "/Delayload:pgenlist.dll")
|
||||
#else
|
||||
#pragma comment(linker, "/Delayload:pgenlista.dll")
|
||||
#endif /* UNICODE_SUPPORT */
|
||||
#pragma comment(linker, "/Delay:UNLOAD")
|
||||
#endif /* _MSC_VER */
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#if defined(DYNAMIC_LOAD)
|
||||
#define WIN_DYN_LOAD
|
||||
#ifdef UNICODE_SUPPORT
|
||||
CSTR pgenlist = "pgenlist";
|
||||
CSTR pgenlistdll = "pgenlist.dll";
|
||||
CSTR psqlodbc = "psqlodbc35w";
|
||||
CSTR psqlodbcdll = "psqlodbc35w.dll";
|
||||
#else
|
||||
CSTR pgenlist = "pgenlista";
|
||||
CSTR pgenlistdll = "pgenlista.dll";
|
||||
CSTR psqlodbc = "psqlodbc30a";
|
||||
CSTR psqlodbcdll = "psqlodbc30a.dll";
|
||||
#endif /* UNICODE_SUPPORT */
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
#define _MSC_DELAY_LOAD_IMPORT
|
||||
#endif /* MSC_VER */
|
||||
#endif /* DYNAMIC_LOAD */
|
||||
#endif /* WIN32 */
|
||||
|
||||
#if defined(_MSC_DELAY_LOAD_IMPORT)
|
||||
/*
|
||||
* Error hook function for delay load import.
|
||||
* Try to load a DLL based on psqlodbc path.
|
||||
*/
|
||||
#if (_MSC_VER >= 1900) /* vc14 or later */
|
||||
#define TRY_DLI_HOOK \
|
||||
__try {
|
||||
#define RELEASE_NOTIFY_HOOK
|
||||
#elif (_MSC_VER < 1300) /* vc6 */
|
||||
extern PfnDliHook __pfnDliFailureHook;
|
||||
extern PfnDliHook __pfnDliNotifyHook;
|
||||
#define TRY_DLI_HOOK \
|
||||
__try { \
|
||||
__pfnDliFailureHook = DliErrorHook; \
|
||||
__pfnDliNotifyHook = DliErrorHook;
|
||||
#define RELEASE_NOTIFY_HOOK \
|
||||
__pfnDliNotifyHook = NULL;
|
||||
#else /* vc7 ~ 12 */
|
||||
extern PfnDliHook __pfnDliFailureHook2;
|
||||
extern PfnDliHook __pfnDliNotifyHook2;
|
||||
#define TRY_DLI_HOOK \
|
||||
__try { \
|
||||
__pfnDliFailureHook2 = DliErrorHook; \
|
||||
__pfnDliNotifyHook2 = DliErrorHook;
|
||||
#define RELEASE_NOTIFY_HOOK \
|
||||
__pfnDliNotifyHook2 = NULL;
|
||||
#endif /* _MSC_VER */
|
||||
#else
|
||||
#define TRY_DLI_HOOK \
|
||||
__try {
|
||||
#define RELEASE_NOTIFY_HOOK
|
||||
#endif /* _MSC_DELAY_LOAD_IMPORT */
|
||||
|
||||
#if defined(_MSC_DELAY_LOAD_IMPORT)
|
||||
static BOOL loaded_pgenlist = FALSE;
|
||||
static HMODULE enlist_module = NULL;
|
||||
static BOOL loaded_psqlodbc = FALSE;
|
||||
/*
|
||||
* Load a DLL based on psqlodbc path.
|
||||
*/
|
||||
HMODULE MODULE_load_from_psqlodbc_path(const char *module_name)
|
||||
{
|
||||
extern HINSTANCE s_hModule;
|
||||
HMODULE hmodule = NULL;
|
||||
char szFileName[MAX_PATH];
|
||||
|
||||
if (GetModuleFileName(s_hModule, szFileName, sizeof(szFileName)) > 0)
|
||||
{
|
||||
char drive[_MAX_DRIVE], dir[_MAX_DIR], sysdir[MAX_PATH];
|
||||
|
||||
_splitpath(szFileName, drive, dir, NULL, NULL);
|
||||
GetSystemDirectory(sysdir, MAX_PATH);
|
||||
SPRINTF_FIXED(szFileName, "%s%s%s.dll", drive, dir, module_name);
|
||||
if (_strnicmp(szFileName, sysdir, strlen(sysdir)) != 0)
|
||||
{
|
||||
hmodule = LoadLibraryEx(szFileName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
|
||||
MYLOG(0, "psqlodbc path based %s loaded module=%p\n", module_name, hmodule);
|
||||
}
|
||||
}
|
||||
return hmodule;
|
||||
}
|
||||
|
||||
|
||||
static FARPROC WINAPI
|
||||
DliErrorHook(unsigned dliNotify,
|
||||
PDelayLoadInfo pdli)
|
||||
{
|
||||
HMODULE hmodule = NULL;
|
||||
const char* call_module = NULL;
|
||||
|
||||
MYLOG(0, "Dli%sHook %s Notify=%d\n", (dliFailLoadLib == dliNotify || dliFailGetProc == dliNotify) ? "Error" : "Notify", NULL != pdli->szDll ? pdli->szDll : pdli->dlp.szProcName, dliNotify);
|
||||
switch (dliNotify)
|
||||
{
|
||||
case dliNotePreLoadLibrary:
|
||||
case dliFailLoadLib:
|
||||
RELEASE_NOTIFY_HOOK
|
||||
if (_strnicmp(pdli->szDll, pgenlist, strlen(pgenlist)) == 0)
|
||||
call_module = pgenlist;
|
||||
else if (_strnicmp(pdli->szDll, psqlodbc, strlen(psqlodbc)) == 0)
|
||||
call_module = psqlodbc;
|
||||
if (call_module)
|
||||
{
|
||||
if (hmodule = MODULE_load_from_psqlodbc_path(call_module), NULL == hmodule)
|
||||
hmodule = LoadLibrary(call_module);
|
||||
if (NULL != hmodule)
|
||||
{
|
||||
if (pgenlist == call_module)
|
||||
loaded_pgenlist = TRUE;
|
||||
else if (psqlodbc == call_module)
|
||||
loaded_psqlodbc = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return (FARPROC) hmodule;
|
||||
}
|
||||
|
||||
void AlreadyLoadedPsqlodbc(void)
|
||||
{
|
||||
loaded_psqlodbc = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* unload delay loaded libraries.
|
||||
*/
|
||||
|
||||
typedef BOOL (WINAPI *UnloadFunc)(LPCSTR);
|
||||
void CleanupDelayLoadedDLLs(void)
|
||||
{
|
||||
BOOL success;
|
||||
#if (_MSC_VER < 1300) /* VC6 DELAYLOAD IMPORT */
|
||||
UnloadFunc func = __FUnloadDelayLoadedDLL;
|
||||
#else
|
||||
UnloadFunc func = __FUnloadDelayLoadedDLL2;
|
||||
#endif
|
||||
/* The dll names are case sensitive for the unload helper */
|
||||
if (loaded_pgenlist)
|
||||
{
|
||||
if (enlist_module != NULL)
|
||||
{
|
||||
MYLOG(0, "Freeing Library %s\n", pgenlistdll);
|
||||
FreeLibrary(enlist_module);
|
||||
}
|
||||
MYLOG(0, "%s unloading\n", pgenlistdll);
|
||||
success = (*func)(pgenlistdll);
|
||||
MYLOG(0, "%s unloaded success=%d\n", pgenlistdll, success);
|
||||
loaded_pgenlist = FALSE;
|
||||
}
|
||||
if (loaded_psqlodbc)
|
||||
{
|
||||
MYLOG(0, "%s unloading\n", psqlodbcdll);
|
||||
success = (*func)(psqlodbcdll);
|
||||
MYLOG(0, "%s unloaded success=%d\n", psqlodbcdll, success);
|
||||
loaded_psqlodbc = FALSE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#else
|
||||
void CleanupDelayLoadedDLLs(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif /* _MSC_DELAY_LOAD_IMPORT */
|
||||
|
||||
#ifdef _HANDLE_ENLIST_IN_DTC_
|
||||
RETCODE CALL_EnlistInDtc(ConnectionClass *conn, void *pTra, int method)
|
||||
{
|
||||
RETCODE ret;
|
||||
BOOL loaded = TRUE;
|
||||
|
||||
#if defined(_MSC_DELAY_LOAD_IMPORT)
|
||||
if (!loaded_pgenlist)
|
||||
{
|
||||
TRY_DLI_HOOK
|
||||
ret = EnlistInDtc(conn, pTra, method);
|
||||
}
|
||||
__except ((GetExceptionCode() & 0xffff) == ERROR_MOD_NOT_FOUND ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
|
||||
if (enlist_module = MODULE_load_from_psqlodbc_path(pgenlist), NULL == enlist_module)
|
||||
loaded = FALSE;
|
||||
else
|
||||
ret = EnlistInDtc(conn, pTra, method);
|
||||
}
|
||||
if (loaded)
|
||||
loaded_pgenlist = TRUE;
|
||||
RELEASE_NOTIFY_HOOK
|
||||
}
|
||||
else
|
||||
ret = EnlistInDtc(conn, pTra, method);
|
||||
#else
|
||||
ret = EnlistInDtc(conn, pTra, method);
|
||||
loaded_pgenlist = TRUE;
|
||||
#endif /* _MSC_DELAY_LOAD_IMPORT */
|
||||
return ret;
|
||||
}
|
||||
RETCODE CALL_DtcOnDisconnect(ConnectionClass *conn)
|
||||
{
|
||||
if (loaded_pgenlist)
|
||||
return DtcOnDisconnect(conn);
|
||||
return FALSE;
|
||||
}
|
||||
RETCODE CALL_IsolateDtcConn(ConnectionClass *conn, BOOL continueConnection)
|
||||
{
|
||||
if (loaded_pgenlist)
|
||||
return IsolateDtcConn(conn, continueConnection);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void *CALL_GetTransactionObject(HRESULT *hres)
|
||||
{
|
||||
void *ret = NULL;
|
||||
BOOL loaded = TRUE;
|
||||
|
||||
#if defined(_MSC_DELAY_LOAD_IMPORT)
|
||||
if (!loaded_pgenlist)
|
||||
{
|
||||
TRY_DLI_HOOK
|
||||
ret = GetTransactionObject(hres);
|
||||
}
|
||||
__except ((GetExceptionCode() & 0xffff) == ERROR_MOD_NOT_FOUND ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
|
||||
if (enlist_module = MODULE_load_from_psqlodbc_path(pgenlist), NULL == enlist_module)
|
||||
loaded = FALSE;
|
||||
else
|
||||
ret = GetTransactionObject(hres);
|
||||
}
|
||||
if (loaded)
|
||||
loaded_pgenlist = TRUE;
|
||||
RELEASE_NOTIFY_HOOK
|
||||
}
|
||||
else
|
||||
ret = GetTransactionObject(hres);
|
||||
#else
|
||||
ret = GetTransactionObject(hres);
|
||||
loaded_pgenlist = TRUE;
|
||||
#endif /* _MSC_DELAY_LOAD_IMPORT */
|
||||
return ret;
|
||||
}
|
||||
void CALL_ReleaseTransactionObject(void *pObj)
|
||||
{
|
||||
if (loaded_pgenlist)
|
||||
ReleaseTransactionObject(pObj);
|
||||
return;
|
||||
}
|
||||
#endif /* _HANDLE_ENLIST_IN_DTC_ */
|
Reference in New Issue
Block a user