2002-06-05 11:57:14 +02:00
|
|
|
/*
|
|
|
|
* mod_loader.cpp
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2008-12-16 12:30:35 +01:00
|
|
|
// required to use activation context API structures
|
|
|
|
#define _WIN32_WINNT 0x0501
|
|
|
|
|
2006-07-27 14:19:30 +02:00
|
|
|
#include "firebird.h"
|
2002-06-05 11:57:14 +02:00
|
|
|
#include "../jrd/os/mod_loader.h"
|
|
|
|
#include <windows.h>
|
|
|
|
|
2002-11-17 16:46:24 +01:00
|
|
|
typedef Firebird::string string;
|
2004-02-08 18:08:34 +01:00
|
|
|
typedef Firebird::PathName PathName;
|
2002-11-17 16:46:24 +01:00
|
|
|
|
2002-06-05 11:57:14 +02:00
|
|
|
/// This is the Win32 implementation of the mod_loader abstraction.
|
|
|
|
|
2008-12-16 12:30:35 +01:00
|
|
|
HINSTANCE hDllInst = 0;
|
|
|
|
BOOL bEmbedded = false;
|
|
|
|
|
|
|
|
/// activation context API prototypes
|
|
|
|
typedef HANDLE (WINAPI * PFN_CAC)(PCACTCTXA pActCtx);
|
|
|
|
|
|
|
|
typedef BOOL (WINAPI * PFN_FINDAC)(DWORD dwFlags,
|
|
|
|
const GUID *lpExtensionGuid,
|
|
|
|
ULONG ulSectionId,
|
|
|
|
LPCSTR lpStringToFind,
|
|
|
|
PACTCTX_SECTION_KEYED_DATA ReturnedData);
|
|
|
|
|
|
|
|
typedef void (WINAPI * PFN_RAC)(HANDLE hActCtx);
|
|
|
|
|
|
|
|
typedef BOOL (WINAPI * PFN_AAC)(HANDLE hActCtx, ULONG_PTR *lpCookie);
|
|
|
|
|
|
|
|
typedef BOOL (WINAPI * PFN_DAC)(DWORD dwFlags, ULONG_PTR ulCookie);
|
|
|
|
/// end of activation context API prototypes
|
|
|
|
|
|
|
|
|
|
|
|
template <typename PFN>
|
|
|
|
class WinApiFunction
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
WinApiFunction(const char *dllName, const char *fnName)
|
|
|
|
{
|
|
|
|
m_ptr = NULL;
|
|
|
|
const HMODULE hDll = GetModuleHandle(dllName);
|
|
|
|
if (hDll)
|
|
|
|
m_ptr = (PFN) GetProcAddress(hDll, fnName);
|
|
|
|
}
|
|
|
|
|
|
|
|
~WinApiFunction()
|
|
|
|
{}
|
|
|
|
|
|
|
|
PFN operator* () const
|
|
|
|
{ return m_ptr; }
|
|
|
|
|
|
|
|
operator bool() const
|
|
|
|
{ return (m_ptr != NULL); }
|
|
|
|
|
|
|
|
private:
|
|
|
|
PFN m_ptr;
|
|
|
|
};
|
|
|
|
|
|
|
|
const char* sKernel32 = "kernel32.dll";
|
|
|
|
|
|
|
|
|
|
|
|
class ContextActivator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ContextActivator() :
|
|
|
|
mFindActCtxSectionString(sKernel32, "FindActCtxSectionStringA"),
|
|
|
|
mCreateActCtx(sKernel32, "CreateActCtxA"),
|
|
|
|
mReleaseActCtx(sKernel32, "ReleaseActCtx"),
|
|
|
|
mActivateActCtx(sKernel32, "ActivateActCtx"),
|
|
|
|
mDeactivateActCtx(sKernel32, "DeactivateActCtx")
|
|
|
|
{
|
|
|
|
hActCtx = INVALID_HANDLE_VALUE;
|
|
|
|
|
|
|
|
// if we don't use MSVC then we don't use MS CRT ?
|
|
|
|
#ifndef _MSC_VER
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!bEmbedded || !mCreateActCtx)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ACTCTX_SECTION_KEYED_DATA ackd;
|
|
|
|
memset(&ackd, 0, sizeof(ackd));
|
|
|
|
ackd.cbSize = sizeof(ackd);
|
|
|
|
|
|
|
|
// if CRT already present in some activation context then nothing to do
|
|
|
|
if ((*mFindActCtxSectionString)
|
|
|
|
(0, NULL,
|
|
|
|
ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
|
|
|
|
#if _MSC_VER == 1400
|
|
|
|
"msvcr80.dll",
|
|
|
|
#else
|
|
|
|
#error Specify CRT DLL name here !
|
|
|
|
#endif
|
|
|
|
&ackd))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// create and use activation context from our own manifest
|
|
|
|
ACTCTXA actCtx;
|
|
|
|
memset(&actCtx, 0, sizeof(actCtx));
|
|
|
|
actCtx.cbSize = sizeof(actCtx);
|
|
|
|
actCtx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
|
|
|
|
actCtx.lpResourceName = ISOLATIONAWARE_MANIFEST_RESOURCE_ID;
|
|
|
|
actCtx.hModule = hDllInst;
|
|
|
|
|
|
|
|
if (actCtx.hModule)
|
|
|
|
{
|
|
|
|
char name[1024];
|
|
|
|
GetModuleFileName(actCtx.hModule, name, sizeof(name));
|
|
|
|
actCtx.lpSource = name;
|
|
|
|
|
|
|
|
hActCtx = (*mCreateActCtx) (&actCtx);
|
|
|
|
if (hActCtx != INVALID_HANDLE_VALUE)
|
|
|
|
(*mActivateActCtx) (hActCtx, &mCookie);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
~ContextActivator()
|
|
|
|
{
|
|
|
|
if (hActCtx != INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
(*mDeactivateActCtx)(0, mCookie);
|
|
|
|
(*mReleaseActCtx)(hActCtx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
WinApiFunction<PFN_FINDAC> mFindActCtxSectionString;
|
|
|
|
WinApiFunction<PFN_CAC> mCreateActCtx;
|
|
|
|
WinApiFunction<PFN_RAC> mReleaseActCtx;
|
|
|
|
WinApiFunction<PFN_AAC> mActivateActCtx;
|
|
|
|
WinApiFunction<PFN_DAC> mDeactivateActCtx;
|
|
|
|
|
|
|
|
HANDLE hActCtx;
|
|
|
|
ULONG_PTR mCookie;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2002-06-05 11:57:14 +02:00
|
|
|
class Win32Module : public ModuleLoader::Module
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Win32Module(HMODULE m) : module(m) {}
|
|
|
|
~Win32Module();
|
2002-11-17 16:46:24 +01:00
|
|
|
void *findSymbol(const string&);
|
2008-12-05 02:20:14 +01:00
|
|
|
|
2002-06-05 11:57:14 +02:00
|
|
|
private:
|
|
|
|
HMODULE module;
|
|
|
|
};
|
|
|
|
|
2004-02-08 18:08:34 +01:00
|
|
|
bool ModuleLoader::isLoadableModule(const PathName& module)
|
2002-06-05 11:57:14 +02:00
|
|
|
{
|
2008-12-16 12:30:35 +01:00
|
|
|
ContextActivator ctx;
|
|
|
|
|
2003-03-14 12:28:10 +01:00
|
|
|
LPCSTR pszName = module.c_str();
|
2008-04-01 17:27:16 +02:00
|
|
|
HINSTANCE hMod = LoadLibraryEx(pszName, 0,
|
|
|
|
LOAD_WITH_ALTERED_SEARCH_PATH | LOAD_LIBRARY_AS_DATAFILE);
|
|
|
|
|
2003-03-14 12:28:10 +01:00
|
|
|
if (hMod) {
|
|
|
|
FreeLibrary((HMODULE)hMod);
|
|
|
|
}
|
|
|
|
return hMod != 0;
|
2002-06-05 11:57:14 +02:00
|
|
|
}
|
|
|
|
|
2004-02-08 18:08:34 +01:00
|
|
|
void ModuleLoader::doctorModuleExtention(Firebird::PathName& name)
|
2002-06-05 11:57:14 +02:00
|
|
|
{
|
2004-02-08 18:08:34 +01:00
|
|
|
PathName::size_type pos = name.rfind(".dll");
|
|
|
|
if (pos != PathName::npos && pos == name.length() - 4)
|
2002-11-17 16:46:24 +01:00
|
|
|
return;
|
2002-06-05 11:57:14 +02:00
|
|
|
name += ".dll";
|
|
|
|
}
|
|
|
|
|
2004-02-08 18:08:34 +01:00
|
|
|
ModuleLoader::Module *ModuleLoader::loadModule(const Firebird::PathName& modPath)
|
2002-06-05 11:57:14 +02:00
|
|
|
{
|
2008-12-16 12:30:35 +01:00
|
|
|
ContextActivator ctx;
|
|
|
|
|
2008-04-01 17:27:16 +02:00
|
|
|
HMODULE module = LoadLibraryEx(modPath.c_str(), 0, LOAD_WITH_ALTERED_SEARCH_PATH);
|
2002-06-05 11:57:14 +02:00
|
|
|
if (!module)
|
|
|
|
return 0;
|
2008-12-05 02:20:14 +01:00
|
|
|
|
2002-09-25 19:12:16 +02:00
|
|
|
return FB_NEW(*getDefaultMemoryPool()) Win32Module(module);
|
2002-06-05 11:57:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Win32Module::~Win32Module()
|
|
|
|
{
|
|
|
|
if (module)
|
|
|
|
FreeLibrary(module);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *Win32Module::findSymbol(const Firebird::string& symName)
|
|
|
|
{
|
2002-11-17 16:46:24 +01:00
|
|
|
FARPROC result = GetProcAddress(module, symName.c_str());
|
2002-06-05 11:57:14 +02:00
|
|
|
if (!result)
|
|
|
|
{
|
2002-11-17 16:46:24 +01:00
|
|
|
string newSym = '_' + symName;
|
2002-06-05 11:57:14 +02:00
|
|
|
result = GetProcAddress(module, newSym.c_str());
|
|
|
|
}
|
2002-11-26 09:56:06 +01:00
|
|
|
return (void*) result;
|
2002-06-05 11:57:14 +02:00
|
|
|
}
|