1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | // |
5 | |
6 | // |
7 | // Contains convenience functionality for lazily loading modules |
8 | // and getting entrypoints within them. |
9 | // |
10 | |
11 | #ifndef DelayLoadHelpers_h |
12 | #define DelayLoadHelpers_h |
13 | |
14 | #include "volatile.h" |
15 | |
16 | namespace DelayLoad |
17 | { |
18 | //================================================================================================================= |
19 | // Contains information needed to load and cache a module. Use through |
20 | // the DELAY_LOADED_MODULE macro defined below. |
21 | struct Module |
22 | { |
23 | LPCWSTR const m_wzDllName; |
24 | HMODULE m_hMod; |
25 | HRESULT m_hr; |
26 | Volatile<bool> m_fInitialized; |
27 | |
28 | // Returns a non-ref-counted HMODULE; will load the module if necessary. |
29 | // Do not FreeLibrary the returned value. |
30 | HRESULT GetValue(HMODULE *pHMODULE); |
31 | }; |
32 | } |
33 | |
34 | //===================================================================================================================== |
35 | // Use at global scope to declare a delay loaded module represented as a |
36 | // DelayLoad::Module instance. The module may then be accessed as |
37 | // 'DelayLoad::Modules::DLL_NAME'. |
38 | // |
39 | // Parameters: |
40 | // DLL_NAME - the simple name (without extension) of the DLL. |
41 | // |
42 | // Example: |
43 | // DELAY_LOADED_MODULE(Kernel32); |
44 | // void Foo() { |
45 | // HMODULE hModKernel32 = nullptr; |
46 | // IfFailThrow(DelayLoad::Modules::Kernel32.GetValue(&hModKernel32)); |
47 | // // Use hModKernel32 as needed. Do not FreeLibrary the value! |
48 | // } |
49 | |
50 | #define DELAY_LOADED_MODULE(DLL_NAME) \ |
51 | namespace DelayLoad { \ |
52 | namespace Modules { \ |
53 | SELECTANY Module DLL_NAME = { L#DLL_NAME W(".dll"), nullptr, S_OK, false }; \ |
54 | } \ |
55 | } |
56 | |
57 | namespace DelayLoad |
58 | { |
59 | //================================================================================================================= |
60 | // Contains information needed to load a function pointer from a DLL. Builds |
61 | // on the DelayLoad::Module functionality, and should be used through |
62 | // the DELAY_LOADED_FUNCTION macro defined below. |
63 | struct Function |
64 | { |
65 | Module * const m_pModule; |
66 | LPCSTR const m_szFunctionName; |
67 | PVOID m_pvFunction; |
68 | HRESULT m_hr; |
69 | Volatile<bool> m_fInitialized; |
70 | |
71 | // On success, ppvFunc is set to point to the entrypoint corresponding to |
72 | // m_szFunctionName as exported from m_pModule. |
73 | HRESULT GetValue(LPVOID * ppvFunc); |
74 | |
75 | // Convenience function that does the necessary casting for you. |
76 | template <typename FnT> inline |
77 | HRESULT GetValue(FnT ** ppFunc) |
78 | { |
79 | return GetValue(reinterpret_cast<LPVOID*>(ppFunc)); |
80 | } |
81 | }; |
82 | } |
83 | |
84 | //===================================================================================================================== |
85 | // Use at global scope to declare a delay loaded function and its associated module, |
86 | // represented as DelayLoad::Function and DelayLoad::Module instances, respectively. |
87 | // The function may then be accessed as 'DelayLoad::DLL_NAME::FUNC_NAME', and the |
88 | // module may be access as described in DELAY_LOADED_MODULE's comment. |
89 | // |
90 | // Parameters: |
91 | // DLL_NAME - unquoted simple name (without extension) of the DLL containing |
92 | // the function. |
93 | // FUNC_NAME - unquoted entrypoint name exported from the DLL. |
94 | // |
95 | // Example: |
96 | // DELAY_LOADED_FUNCTION(MyDll, MyFunction); |
97 | // HRESULT Foo(...) { |
98 | // typedef HRESULT MyFunction_t(<args>); |
99 | // MyFunction_t * pFunc = nullptr; |
100 | // IfFailRet(DelayLoad::WinTypes::RoResolveNamespace.GetValue(&pFunc)); |
101 | // return (*pFunc)(...); |
102 | // } |
103 | |
104 | #define DELAY_LOADED_FUNCTION(DLL_NAME, FUNC_NAME) \ |
105 | DELAY_LOADED_MODULE(DLL_NAME) \ |
106 | namespace DelayLoad { \ |
107 | namespace DLL_NAME { \ |
108 | SELECTANY Function FUNC_NAME = { &Modules::##DLL_NAME, #FUNC_NAME, nullptr, S_OK, false }; \ |
109 | } \ |
110 | } |
111 | |
112 | #endif // DelayLoadHelpers_h |
113 | |
114 | |