libmoost
/home/mhx/git/github/libmoost/src/pdl/impl/dl_win32.ipp
Go to the documentation of this file.
00001 #include <windows.h>
00002 
00003 namespace moost { namespace pdl {
00004 
00005 class dynamic_library_impl : public dynamic_library_if
00006 {
00007 public:
00008    dynamic_library_impl(const std::string& library_name, bool resolve_symbols);
00009 
00010    ~dynamic_library_impl();
00011 
00012    void *get_symbol_by_name(const std::string& symbol_name) const;
00013 
00014    const std::string& library_path() const
00015    {
00016       return m_library_path;
00017    }
00018 
00019 private:
00020    typedef HMODULE library_handle_t;
00021 
00022    static library_handle_t open_library(const std::string& library_name, bool resolve_symbols);
00023    DWORD get_last_error() const;
00024    std::string format_error(DWORD error) const;
00025    bool is_file_not_found_error(DWORD error) const;
00026 
00027    std::string m_library_path;
00028    library_handle_t m_library;
00029 };
00030 
00031 dynamic_library_impl::dynamic_library_impl(const std::string& library_name, bool resolve_symbols)
00032 {
00033    std::string lib_path(library_name);
00034    DWORD error;
00035 
00036    m_library = open_library(lib_path, resolve_symbols);
00037 
00038    if (!m_library)
00039    {
00040       error = get_last_error();
00041 
00042       if (is_file_not_found_error(error))
00043       {
00044          lib_path += ".dll";
00045 
00046          m_library = open_library(lib_path, resolve_symbols);
00047 
00048          if (!m_library)
00049          {
00050             error = get_last_error();
00051          }
00052       }
00053    }
00054 
00055    if (!m_library)
00056    {
00057       std::string errstr = format_error(error);
00058 
00059       if (is_file_not_found_error(error))
00060       {
00061          throw library_not_found_error(errstr);
00062       }
00063       else
00064       {
00065          throw library_load_error(errstr);
00066       }
00067    }
00068 
00069    m_library_path = lib_path;
00070 }
00071 
00072 bool dynamic_library_impl::is_file_not_found_error(DWORD error) const
00073 {
00074    return error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND;
00075 }
00076 
00077 dynamic_library_impl::~dynamic_library_impl()
00078 {
00079    try
00080    {
00081       ::FreeLibrary(m_library);
00082    }
00083    catch (...)
00084    {
00085       // there's nothing we can do here
00086    }
00087 }
00088 
00089 dynamic_library_impl::library_handle_t dynamic_library_impl::open_library(const std::string& library_name, bool resolve_symbols)
00090 {
00091    return ::LoadLibraryExA(library_name.c_str(), NULL, resolve_symbols ? 0 : DONT_RESOLVE_DLL_REFERENCES);
00092 }
00093 
00094 void *dynamic_library_impl::get_symbol_by_name(const std::string& symbol_name) const
00095 {
00096    return static_cast<void *>(::GetProcAddress(m_library, symbol_name.c_str()));
00097 }
00098 
00099 DWORD dynamic_library_impl::get_last_error() const
00100 {
00101    return ::GetLastError();
00102 }
00103 
00104 std::string dynamic_library_impl::format_error(DWORD error) const
00105 {
00106    try
00107    {
00108       LPSTR msg_buf = NULL;
00109       const DWORD res =
00110          ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
00111                           NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00112                           reinterpret_cast<LPSTR>(&msg_buf), 0, NULL);
00113       std::string error;
00114       if (res != 0)
00115       {
00116          error.assign(msg_buf);
00117          ::LocalFree(msg_buf);
00118       }
00119       return error;
00120    }
00121    catch (...)
00122    {
00123       return std::string("unknown error");
00124    }
00125 }
00126 
00127 }}