| /** Implementation of the ISAPI_SoapServerFactory class |
| * @file SoapServerFactory.h |
| * @author Christian Aberger |
| * Copyright (C) 2001 WebWare (http://www.webware.at) |
| */ |
| #include <cassert> |
| #include <cstring> // for casecmp |
| #include <map> |
| #include <string> |
| #include "ISAPI_SoapServerFactory.h" |
| #include "casecmpless.h" |
| using namespace std; |
| |
| class CriticalSectionLock { |
| public: |
| CriticalSectionLock(CRITICAL_SECTION *pcs) : m_pcs(pcs) { |
| assert(NULL != pcs); |
| ::EnterCriticalSection(pcs); |
| } |
| ~CriticalSectionLock() { |
| ::LeaveCriticalSection(m_pcs); |
| } |
| protected: |
| CRITICAL_SECTION *m_pcs; |
| }; |
| |
| |
| ISAPI_SoapServerFactory *ISAPI_SoapServerFactory::m_pInstance = NULL; |
| |
| mod_gsoap_interface::mod_gsoap_interface() |
| : fsoap_init(NULL) |
| , fsoap_serve(NULL) |
| , fsoap_delete(NULL) |
| , fsoap_done(NULL) |
| , fsoap_end(NULL) |
| , fsoap_register_plugin_arg(NULL) |
| , fsoap_lookup_plugin(NULL) |
| , fmod_gsoap_init(NULL) |
| , fmod_gsoap_terminate(NULL) |
| , reserved(NULL) |
| { |
| } |
| mod_gsoap_interface::mod_gsoap_interface(const mod_gsoap_interface& intf) { |
| *this = intf; |
| } |
| mod_gsoap_interface& mod_gsoap_interface::operator=(const mod_gsoap_interface& intf) { |
| fsoap_init = intf.fsoap_init; |
| fsoap_serve = intf.fsoap_serve; |
| fsoap_delete = intf.fsoap_delete; |
| fsoap_done = intf.fsoap_done; |
| fsoap_end = intf.fsoap_end; |
| fsoap_register_plugin_arg = intf.fsoap_register_plugin_arg; |
| fsoap_lookup_plugin = intf.fsoap_lookup_plugin; |
| fmod_gsoap_init = intf.fmod_gsoap_init; |
| fmod_gsoap_terminate = intf.fmod_gsoap_terminate; |
| return *this; |
| } |
| /** Have all entry points been found in the gosap server library ? |
| @return true if all entry points have been assigned successfully. |
| */ |
| bool mod_gsoap_interface::linked() const { |
| return |
| NULL != fsoap_init && |
| NULL != fsoap_serve && |
| NULL != fsoap_done && |
| NULL != fsoap_end && |
| NULL != fsoap_register_plugin_arg && |
| NULL != fsoap_lookup_plugin; |
| // don't check for fsoap_delete, only servers with classes have it. |
| } |
| |
| SoapDll::SoapDll() |
| : m_hDll(NULL) |
| { |
| } |
| SoapDll::SoapDll(const SoapDll& dll) { |
| *this = dll; |
| } |
| SoapDll& SoapDll::operator=(const SoapDll& dll) { |
| m_hDll = dll.m_hDll; |
| m_strLastError = dll.m_strLastError; |
| m_interface = dll.m_interface; |
| return *this; |
| } |
| bool SoapDll::unload() { |
| bool bRet = true; |
| if (NULL != m_hDll) { |
| if (NULL != m_interface.fmod_gsoap_terminate) { |
| int nRet = (*m_interface.fmod_gsoap_terminate)(); |
| } |
| BOOL bFree = ::FreeLibrary(m_hDll); |
| bRet = bFree ? true : false; |
| } |
| return bRet; |
| } |
| SoapDll::~SoapDll() { |
| } |
| /** |
| @param pszPath the name of the dll to load. |
| */ |
| bool SoapDll::load(const char *pszPath) { |
| bool bRet = true; |
| if (NULL == m_hDll) { |
| m_strLastError.erase(); |
| m_hDll = LoadLibrary(pszPath); |
| if (NULL != m_hDll) { |
| bRet = GetEntryPoints(pszPath); |
| } else { |
| LPVOID lpMsgBuf = NULL; |
| FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, |
| NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language |
| (LPTSTR) &lpMsgBuf, 0, NULL); |
| m_strLastError = "Attempt to load '" + string(pszPath) + "' failed. "; |
| m_strLastError += (LPCTSTR)lpMsgBuf; |
| LocalFree(lpMsgBuf); |
| bRet = false; |
| } |
| } |
| assert(false == bRet || (NULL != m_hDll)); |
| return bRet; |
| } |
| const char *SoapDll::getLastError() const { |
| return m_strLastError.c_str(); |
| } |
| static isapi_gsoap_server_fn GetFunction( |
| HMODULE hDll, |
| const char *pszFunctionName, |
| string& strErrorMessage, |
| const char *pszPath) |
| { |
| assert(NULL != pszFunctionName); |
| |
| isapi_gsoap_server_fn fn = NULL; |
| if (NULL != hDll) { |
| strErrorMessage.erase(); |
| FARPROC DllEntryPoint = GetProcAddress(hDll, pszFunctionName); // Find entry point. |
| if (NULL != DllEntryPoint) { |
| fn = reinterpret_cast<isapi_gsoap_server_fn>(DllEntryPoint); |
| } else { |
| strErrorMessage = "Entry Point '"; |
| strErrorMessage += pszFunctionName; |
| strErrorMessage += "' not found in dll '" + string(pszPath) + "'."; |
| } |
| } |
| return fn; |
| } |
| /** Find the address of all entry points that we must use. */ |
| bool SoapDll::GetEntryPoints(const char *pszPath) { |
| assert(NULL != m_hDll); |
| |
| string strTmp; |
| m_interface.fsoap_init = GetFunction(m_hDll, "soap_init", m_strLastError, pszPath); |
| m_interface.fsoap_serve = GetFunction(m_hDll, "soap_serve", m_strLastError, pszPath); |
| m_interface.fsoap_delete = (isapi_soap_delete_fn)GetFunction(m_hDll, "soap_delete", strTmp, pszPath); // soap_delete may be missing for non - cpp |
| m_interface.fsoap_done = GetFunction(m_hDll, "soap_done", m_strLastError, pszPath); |
| m_interface.fsoap_end = GetFunction(m_hDll, "soap_end", m_strLastError, pszPath); |
| m_interface.fsoap_register_plugin_arg = (isapi_soap_register_plugin_fn)GetFunction(m_hDll, "soap_register_plugin_arg", m_strLastError, pszPath); |
| m_interface.fsoap_lookup_plugin = (isapi_soap_lookup_plugin_fn)GetFunction(m_hDll, "soap_lookup_plugin", m_strLastError, pszPath); |
| m_interface.fmod_gsoap_init = (mod_gsoap_init_fn)GetFunction(m_hDll, "mod_gsoap_init", strTmp, pszPath); |
| m_interface.fmod_gsoap_terminate = (mod_gsoap_terminate_fn)GetFunction(m_hDll, "mod_gsoap_terminate", strTmp, pszPath); |
| bool bRet = m_interface.linked(); |
| |
| assert(!bRet || m_interface.linked()); |
| return bRet; |
| } |
| const mod_gsoap_interface *SoapDll::gsoap_interface() const { |
| return m_interface.linked() ? &m_interface : NULL; |
| } |
| /** a map of dll names to the dll handles */ |
| typedef map<string, SoapDll, casecmpless> MapString2Dll; |
| |
| class DllMap : public MapString2Dll { |
| public: |
| DllMap() {}; |
| virtual ~DllMap(); |
| }; |
| DllMap::~DllMap() { |
| for (iterator it = begin(); it != end(); ++it) { |
| bool bRet = it->second.unload(); |
| assert(bRet); |
| } |
| } |
| const char *ISAPI_SoapServerFactory::getLastError() { |
| return m_strError.c_str(); |
| } |
| |
| ISAPI_SoapServerFactory *ISAPI_SoapServerFactory::instance() { |
| if (NULL == m_pInstance) { |
| m_pInstance = new ISAPI_SoapServerFactory; |
| } |
| |
| assert(NULL != m_pInstance); |
| return m_pInstance; |
| } |
| void ISAPI_SoapServerFactory::shutdown() { |
| assert(this == m_pInstance); |
| |
| m_pInstance = NULL; |
| delete this; |
| |
| assert(NULL == m_pInstance); |
| } |
| ISAPI_SoapServerFactory::ISAPI_SoapServerFactory() |
| : m_pDlls(NULL) |
| { |
| ::InitializeCriticalSection(&m_cs); |
| m_pDlls = new DllMap; |
| } |
| ISAPI_SoapServerFactory::~ISAPI_SoapServerFactory() { |
| delete m_pDlls; |
| ::DeleteCriticalSection(&m_cs); |
| } |
| /** @return the function pointers of this dll if they could be loaded and found, else NULL. |
| */ |
| const mod_gsoap_interface *ISAPI_SoapServerFactory::getInterface(const char *pszDll) { |
| const mod_gsoap_interface *pIntf = NULL; |
| CriticalSectionLock lock(&m_cs); |
| m_strError.erase(); |
| if (NULL != pszDll) { |
| DllMap::iterator it = m_pDlls->find(pszDll); |
| if (it == m_pDlls->end()) { |
| SoapDll dll; |
| bool bLoad = dll.load(pszDll); |
| if (bLoad) { |
| const mod_gsoap_interface *pInterface = dll.gsoap_interface(); |
| int nRet = 0; |
| if (NULL != pInterface && NULL != pInterface->fmod_gsoap_init) { |
| nRet = (*pInterface->fmod_gsoap_init)(); |
| if (0 != nRet) { |
| char szBuf[256]; |
| sprintf(szBuf, "failed to initialize %s: mod_gsoap_init returned %d", (const char *)pszDll, nRet); |
| m_strError = szBuf; |
| } |
| } |
| if (0 == nRet) { |
| it = m_pDlls->insert(DllMap::value_type(pszDll, dll)).first; |
| } |
| } else { |
| m_strError = dll.getLastError(); |
| } |
| } |
| if (it != m_pDlls->end()) { |
| const SoapDll& dll = it->second; |
| pIntf = dll.gsoap_interface(); |
| if (NULL == pIntf) { |
| m_strError = dll.getLastError(); |
| } |
| } |
| } |
| return pIntf; |
| } |