1 /*
2 ** i_module.cpp
3 **
4 **---------------------------------------------------------------------------
5 ** Copyright 2016 Braden Obrzut
6 ** All rights reserved.
7 **
8 ** Redistribution and use in source and binary forms, with or without
9 ** modification, are permitted provided that the following conditions
10 ** are met:
11 **
12 ** 1. Redistributions of source code must retain the above copyright
13 **    notice, this list of conditions and the following disclaimer.
14 ** 2. Redistributions in binary form must reproduce the above copyright
15 **    notice, this list of conditions and the following disclaimer in the
16 **    documentation and/or other materials provided with the distribution.
17 ** 3. The name of the author may not be used to endorse or promote products
18 **    derived from this software without specific prior written permission.
19 **
20 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 **---------------------------------------------------------------------------
31 **
32 */
33 
34 #include "i_module.h"
35 
36 #ifdef _WIN32
37 #define WIN32_LEAN_AND_MEAN
38 #include <windows.h>
39 #else
40 #include <dlfcn.h>
41 #endif
42 
43 
44 #ifndef _WIN32
45 #define LoadLibraryA(x) dlopen((x), RTLD_LAZY)
46 #define GetProcAddress(a,b) dlsym((a),(b))
47 #define FreeLibrary(x) dlclose((x))
48 using HMODULE = void*;
49 #endif
50 
Load(std::initializer_list<const char * > libnames)51 bool FModule::Load(std::initializer_list<const char*> libnames)
52 {
53 	for(auto lib : libnames)
54 	{
55 		if(!Open(lib))
56 			continue;
57 
58 		StaticProc *proc;
59 		for(proc = reqSymbols;proc;proc = proc->Next)
60 		{
61 			if(!(proc->Call = GetSym(proc->Name)) && !proc->Optional)
62 			{
63 				Unload();
64 				break;
65 			}
66 		}
67 
68 		if(IsLoaded())
69 			return true;
70 	}
71 
72 	return false;
73 }
74 
Unload()75 void FModule::Unload()
76 {
77 	if(handle)
78 	{
79 		FreeLibrary((HMODULE)handle);
80 		handle = nullptr;
81 	}
82 }
83 
Open(const char * lib)84 bool FModule::Open(const char* lib)
85 {
86 #ifdef _WIN32
87 	if((handle = GetModuleHandleA(lib)) != nullptr)
88 		return true;
89 #else
90 	// Loading an empty string in Linux doesn't do what we expect it to.
91 	if(*lib == '\0')
92 		return false;
93 #endif
94 	handle = LoadLibraryA(lib);
95 	return handle != nullptr;
96 }
97 
GetSym(const char * name)98 void *FModule::GetSym(const char* name)
99 {
100 	return (void *)GetProcAddress((HMODULE)handle, name);
101 }
102 
103 static std::string module_progdir(".");	// current program directory used to look up dynamic libraries. Default to something harmless in case the user didn't set it.
104 
FModule_SetProgDir(const char * progdir)105 void FModule_SetProgDir(const char* progdir)
106 {
107 	module_progdir = progdir;
108 }
109 
FModule_GetProgDir()110 const std::string& FModule_GetProgDir()
111 {
112     return module_progdir;
113 }
114