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 | #include "stdafx.h" |
12 | |
13 | #include "crtwrap.h" |
14 | #include "winwrap.h" |
15 | #include "utilcode.h" |
16 | #include "clrhost.h" |
17 | #include "holder.h" |
18 | #include "delayloadhelpers.h" |
19 | |
20 | namespace DelayLoad |
21 | { |
22 | //================================================================================================================= |
23 | // Used to synchronize initialization. Is not used when initialization has already taken place. |
24 | |
25 | static CRITSEC_COOKIE g_pLock = nullptr; |
26 | |
27 | //================================================================================================================= |
28 | // Creates and initializes g_pLock when first used. |
29 | |
30 | static HRESULT InitializeLock() |
31 | { |
32 | STATIC_CONTRACT_LIMITED_METHOD; |
33 | HRESULT hr = S_OK; |
34 | |
35 | CRITSEC_COOKIE pLock = ClrCreateCriticalSection(CrstLeafLock, CRST_REENTRANCY); |
36 | IfNullRet(pLock); |
37 | if (InterlockedCompareExchangeT<CRITSEC_COOKIE>(&g_pLock, pLock, nullptr) != nullptr) |
38 | { |
39 | ClrDeleteCriticalSection(pLock); |
40 | } |
41 | |
42 | return S_OK; |
43 | } |
44 | |
45 | //================================================================================================================= |
46 | HRESULT Module::GetValue(HMODULE *pHMODULE) |
47 | { |
48 | STATIC_CONTRACT_LIMITED_METHOD; |
49 | HRESULT hr = S_OK; |
50 | |
51 | if (pHMODULE == nullptr) |
52 | { |
53 | return E_INVALIDARG; |
54 | } |
55 | |
56 | if (!m_fInitialized) |
57 | { |
58 | IfFailRet(InitializeLock()); |
59 | |
60 | HModuleHolder hMod = ::LoadLibraryW(m_wzDllName); |
61 | hr = (hMod == nullptr) ? HRESULT_FROM_GetLastError() : S_OK; |
62 | _ASSERTE(FAILED(hr) == (hMod == nullptr)); |
63 | |
64 | { // Lock scope |
65 | CRITSEC_Holder lock(g_pLock); |
66 | if (!m_fInitialized) |
67 | { |
68 | m_hr = hr; |
69 | m_hMod = hMod.Extract(); |
70 | m_fInitialized = true; |
71 | } |
72 | } |
73 | } |
74 | |
75 | _ASSERTE(m_fInitialized); |
76 | *pHMODULE = m_hMod; |
77 | return m_hr; |
78 | } |
79 | |
80 | //================================================================================================================= |
81 | HRESULT Function::GetValue(LPVOID * ppvFunc) |
82 | { |
83 | STATIC_CONTRACT_LIMITED_METHOD; |
84 | HRESULT hr = S_OK; |
85 | |
86 | if (ppvFunc == nullptr) |
87 | { |
88 | return E_INVALIDARG; |
89 | } |
90 | |
91 | if (!m_fInitialized) |
92 | { |
93 | HMODULE hMod = nullptr; |
94 | IfFailRet(m_pModule->GetValue(&hMod)); |
95 | |
96 | LPVOID pvFunc = reinterpret_cast<LPVOID>(::GetProcAddress(hMod, m_szFunctionName)); |
97 | hr = (pvFunc == nullptr) ? HRESULT_FROM_GetLastError() : S_OK; |
98 | |
99 | { // Lock scope |
100 | CRITSEC_Holder lock(g_pLock); |
101 | if (!m_fInitialized) |
102 | { |
103 | m_hr = hr; |
104 | m_pvFunction = pvFunc; |
105 | m_fInitialized = true; |
106 | } |
107 | } |
108 | } |
109 | |
110 | _ASSERTE(m_fInitialized); |
111 | *ppvFunc = m_pvFunction; |
112 | return m_hr; |
113 | } |
114 | } |
115 |