master
h 108 lines 3.01 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 LxssDynamicFunction.h
8
9 Abstract:
10
11 This file contains a helper for accessing dynamically loaded functions.
12
13 --*/
14
15 #pragma once
16
17 enum class DynamicFunctionErrorLogs
18 {
19 None
20 };
21
22 /// <summary>
23 /// Wrapper for a runtime dynamically-loaded function.
24 /// </summary>
25 template <typename FunctionType>
26 class LxssDynamicFunction
27 {
28 public:
29 /// <summary>
30 /// Constructor.
31 /// </summary>
32 LxssDynamicFunction(const wil::shared_hmodule& module, LPCSTR functionName) :
33 m_function{reinterpret_cast<FunctionType*>(GetProcAddress(module.get(), functionName))}, m_module{module}
34 {
35 THROW_LAST_ERROR_IF(!m_function);
36 }
37
38 /// <summary>
39 /// Constructor that loads the module.
40 /// </summary>
41 LxssDynamicFunction(LPCWSTR moduleName, LPCSTR functionName) :
42 LxssDynamicFunction{LoadLibraryHelper(moduleName), functionName}
43 {
44 }
45
46 /// <summary>
47 /// Constructor - this constructs an object that deliberately does not want exceptions (Telemetry Errors on failure)
48 /// With this constructor, the caller must call load() later to attempt to load the specified module
49 /// Note: there is not a default c'tor - we do not want accidental construction
50 /// </summary>
51 LxssDynamicFunction(DynamicFunctionErrorLogs) noexcept
52 {
53 }
54
55 /// <summary>
56 /// Attempt to dynamically load the function
57 /// will return an error instead of throwing on failure - which can be needed when we do not want Error traces on failure
58 /// </summary>
59 HRESULT load(const wil::shared_hmodule& module, LPCSTR functionName) noexcept
60 {
61 m_module.reset();
62
63 m_function = reinterpret_cast<FunctionType*>(GetProcAddress(module.get(), functionName));
64 RETURN_LAST_ERROR_IF_EXPECTED(!m_function);
65 m_module = module;
66 return S_OK;
67 }
68
69 HRESULT load(LPCWSTR moduleName, LPCSTR functionName) noexcept
70 {
71 const wil::shared_hmodule module{LoadLibraryEx(moduleName, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32)};
72 RETURN_LAST_ERROR_IF_EXPECTED(!module);
73 return load(module, functionName);
74 }
75
76 /// <summary>
77 /// Call through to the dynamically loaded function.
78 /// </summary>
79
80 template <typename... Args>
81 decltype(auto) operator()(Args&&... args)
82 {
83 return m_function(std::forward<Args>(args)...);
84 }
85
86 private:
87 static wil::shared_hmodule LoadLibraryHelper(LPCWSTR moduleName)
88 {
89 wil::shared_hmodule module{LoadLibraryEx(moduleName, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32)};
90 THROW_LAST_ERROR_IF_MSG(!module, "Failed to load %ls", moduleName);
91 return module;
92 }
93
94 /// <summary>
95 /// No default constructor.
96 /// </summary>
97 LxssDynamicFunction() = delete;
98
99 /// <summary>
100 /// Dynamically loaded function wrapper.
101 /// </summary>
102 FunctionType* m_function;
103
104 /// <summary>
105 /// Reference to the module containing the dynamically loaded function.
106 /// </summary>
107 wil::shared_hmodule m_module;
108 };