1 /*
2  * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 #ifndef __DLL_H_INCLUDED_
27 #define __DLL_H_INCLUDED_
28 
29 #ifdef _WIN32
30 #include <windows.h>
31 #else
32 typedef void* HMODULE;
33 #endif
34 
35 #include "kludge_c++11.h"
36 
37 #include <memory>
38 #include "tstrings.h"
39 #include "ErrorHandling.h"
40 
41 
42 //
43 // Helper classes to dynamically load DLLs and call the libraries functions.
44 //
45 
46 /**
47  * Library loader.
48  * Usage:
49  * - load a library specified by full path:
50  *      DLL deployLib(FileUtils::combinePath(javaHome, _T("bin\\deploy.dll"));
51  *
52  *  Note: library should be specified by full path (due security reasons)
53  *
54  * - load system library (DLLs from Windows/System32 (SysWow64) directory):
55  *      DLL kernel32Lib("kernel32", Dll::System());
56  */
57 class Dll {
58 public:
59     struct System {};
60 
61     explicit Dll(const tstrings::any &libPath);
62     explicit Dll(const tstrings::any &libName, const System &tag);
63 
64     Dll(const Dll& other);
65 
66     template <class T>
getFunction(const tstrings::any & name,T & addr)67     void getFunction(const tstrings::any &name, T& addr) const {
68         addr = reinterpret_cast<T>(getFunction(name.str(), true));
69     }
70 
71     // returns false & sets addr to NULL if the function not found
72     template <class T>
getFunction(const tstrings::any & name,T & addr,const std::nothrow_t &)73     bool getFunction(const tstrings::any &name, T& addr, const std::nothrow_t &) const {
74         addr = reinterpret_cast<T>(getFunction(name.str(), false));
75         return addr != NULL;
76     }
77 
path()78     const tstring& path() const {
79         return thePath;
80     }
81 
getHandle()82     HMODULE getHandle() const {
83         return handle.get();
84     }
85 
86     static void freeLibrary(HMODULE h);
87 
88     struct LibraryReleaser {
89         typedef HMODULE pointer;
90 
operatorLibraryReleaser91         void operator()(HMODULE h) {
92             freeLibrary(h);
93         }
94     };
95 
96     typedef std::unique_ptr<HMODULE, LibraryReleaser> Handle;
97 
98 private:
99     void* getFunction(const std::string &name, bool throwIfNotFound) const;
100 
101     tstring thePath;
102     Handle handle;
103 };
104 
105 
106 /**
107  * DllFunction template class helps to check is a library function available and call it.
108  * Usage example:
109  *      // RegDeleteKeyExW function (from advapi32.dll) is available on Vista+ or on WinXP 64bit
110  *      // so to avoid dependency on the OS version we have to check if it's available at runtime
111  *
112  *      // the function definition
113  *      typedef LONG (WINAPI *RegDeleteKeyExWFunc)(HKEY hKey, const wchar_t* lpSubKey, REGSAM samDesired, DWORD Reserved);
114  *
115  *      DllFunction<RegDeleteKeyExWFunc> _RegDeleteKeyExW(Dll("advapi32", Dll::System()), "RegDeleteKeyExW");
116  *      if (_RegDeleteKeyExW.available()) {
117  *          // the function is available, call it
118  *          LONG result = _RegDeleteKeyExW(hKey, subkeyName, samDesired, 0);
119  *      } else {
120  *          // the function is not available, handle this
121  *          throw std::exception("RegDeleteKeyExW function is not available");
122  *      }
123  *
124  *      // or we can just try to call the function.
125  *      // if the function is not available, exception with the corresponding description is thrown
126  *      DllFunction<RegDeleteKeyExWFunc> _RegDeleteKeyExW(Dll("advapi32", Dll::System()), "RegDeleteKeyExW");
127  *      LONG result = _RegDeleteKeyExW(hKey, subkeyName, samDesired, 0);
128  */
129 template<class funcType>
130 class DllFunction {
131 public:
DllFunction(const Dll & library,const tstrings::any & funcName)132     DllFunction(const Dll& library, const tstrings::any &funcName)
133             : lib(library), theName(funcName.str()) {
134         lib.getFunction(funcName, funcPtr);
135     }
136 
DllFunction(const std::nothrow_t &,const Dll & library,const tstrings::any & funcName)137     DllFunction(const std::nothrow_t&, const Dll& library,
138                                                 const tstrings::any &funcName)
139             : lib(library), theName(funcName.str()) {
140         lib.getFunction(funcName, funcPtr, std::nothrow);
141     }
142 
available()143     bool available() const {
144         return funcPtr != NULL;
145     }
146 
name()147     std::string name() const {
148         return theName;
149     }
150 
libPath()151     const tstring& libPath() const {
152         return lib.path();
153     }
154 
funcType()155     operator funcType() const {
156         if (!available()) {
157             JP_THROW(tstrings::any()    << theName
158                                         << "() function is not available in "
159                                         << lib.path());
160         }
161         return funcPtr;
162     }
163 
164 private:
165     const Dll lib;
166     funcType funcPtr;
167     std::string theName;
168 };
169 
170 #endif // __DLL_H_INCLUDED_
171