libmoost
|
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 }}