[Tizen] Unify dnetmemoryenumlib terms to match the codebase (#291)
[platform/upstream/coreclr.git] / src / utilcode / delayloadhelpers.cpp
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 }