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 helper types for assembly binding host infrastructure.
8
9#include "common.h"
10
11#include "utilcode.h"
12#include "strsafe.h"
13
14#include "clrprivbinderutil.h"
15
16inline
17LPWSTR CopyStringThrowing(
18 LPCWSTR wszString)
19{
20 CONTRACTL
21 {
22 THROWS;
23 GC_NOTRIGGER;
24 }
25 CONTRACTL_END;
26
27 NewArrayHolder<WCHAR> wszDup = NULL;
28 if (wszString != NULL)
29 {
30 size_t wszLen = wcslen(wszString);
31 wszDup = new WCHAR[wszLen + 1];
32 IfFailThrow(StringCchCopy(wszDup, wszLen + 1, wszString));
33 }
34 wszDup.SuppressRelease();
35
36 return wszDup;
37}
38
39
40namespace CLRPrivBinderUtil
41{
42 //---------------------------------------------------------------------------------------------
43 CLRPrivResourcePathImpl::CLRPrivResourcePathImpl(LPCWSTR wzPath)
44 : m_wzPath(CopyStringThrowing(wzPath))
45 { STANDARD_VM_CONTRACT; }
46
47 //---------------------------------------------------------------------------------------------
48 HRESULT CLRPrivResourcePathImpl::GetPath(
49 DWORD cchBuffer,
50 LPDWORD pcchBuffer,
51 __inout_ecount_part(cchBuffer, *pcchBuffer) LPWSTR wzBuffer)
52 {
53 LIMITED_METHOD_CONTRACT;
54 HRESULT hr = S_OK;
55
56 if (pcchBuffer == nullptr)
57 IfFailRet(E_INVALIDARG);
58
59 *pcchBuffer = (DWORD)wcslen(m_wzPath);
60
61 if (wzBuffer != nullptr)
62 {
63 if (FAILED(StringCchCopy(wzBuffer, cchBuffer, m_wzPath)))
64 IfFailRet(HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER));
65 }
66
67 return hr;
68 }
69
70 //---------------------------------------------------------------------------------------------
71 CLRPrivResourceStreamImpl::CLRPrivResourceStreamImpl(IStream * pStream)
72 : m_pStream(pStream)
73 {
74 LIMITED_METHOD_CONTRACT;
75 pStream->AddRef();
76 }
77
78 //---------------------------------------------------------------------------------------------
79 HRESULT CLRPrivResourceStreamImpl::GetStream(
80 REFIID riid,
81 LPVOID * ppvStream)
82 {
83 LIMITED_METHOD_CONTRACT;
84 return m_pStream->QueryInterface(riid, ppvStream);
85 }
86
87 //---------------------------------------------------------------------------------------------
88 HRESULT AssemblyVersion::Initialize(
89 IAssemblyName * pAssemblyName)
90 {
91 WRAPPER_NO_CONTRACT;
92 HRESULT hr = pAssemblyName->GetVersion(&dwMajorMinor, &dwBuildRevision);
93 if (hr == FUSION_E_INVALID_NAME)
94 {
95 hr = S_FALSE;
96 }
97 return hr;
98 }
99
100 //---------------------------------------------------------------------------------------------
101 HRESULT AssemblyVersion::Initialize(
102 ICLRPrivAssemblyInfo * pAssemblyInfo)
103 {
104 WRAPPER_NO_CONTRACT;
105 return pAssemblyInfo->GetAssemblyVersion(&wMajor, &wMinor, &wBuild, &wRevision);
106 }
107
108 //---------------------------------------------------------------------------------------------
109 HRESULT PublicKey::Initialize(
110 ICLRPrivAssemblyInfo * pAssemblyInfo)
111 {
112 LIMITED_METHOD_CONTRACT;
113 HRESULT hr = S_OK;
114
115 VALIDATE_PTR_RET(pAssemblyInfo);
116
117 Uninitialize();
118
119 DWORD cbKeyDef = 0;
120 hr = pAssemblyInfo->GetAssemblyPublicKey(cbKeyDef, &cbKeyDef, nullptr);
121
122 if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))
123 {
124 if (cbKeyDef != 0)
125 {
126 NewArrayHolder<BYTE> pbKeyDef = new (nothrow) BYTE[cbKeyDef];
127 IfNullRet(pbKeyDef);
128
129 if (SUCCEEDED(hr = pAssemblyInfo->GetAssemblyPublicKey(cbKeyDef, &cbKeyDef, pbKeyDef)))
130 {
131 m_key = pbKeyDef.Extract();
132 m_key_owned = true;
133 m_size = cbKeyDef;
134 }
135 }
136 }
137
138 return hr;
139 }
140
141 //---------------------------------------------------------------------------------------------
142 HRESULT PublicKeyToken::Initialize(
143 BYTE * pbKeyToken,
144 DWORD cbKeyToken)
145 {
146 LIMITED_METHOD_CONTRACT;
147
148 VALIDATE_CONDITION((pbKeyToken == nullptr) == (cbKeyToken == 0), return E_INVALIDARG);
149 VALIDATE_ARG_RET(cbKeyToken == 0 || cbKeyToken == PUBLIC_KEY_TOKEN_LEN1);
150
151 m_cbKeyToken = cbKeyToken;
152
153 if (pbKeyToken != nullptr)
154 {
155 memcpy(m_rbKeyToken, pbKeyToken, PUBLIC_KEY_TOKEN_LEN1);
156 }
157 else
158 {
159 memset(m_rbKeyToken, 0, PUBLIC_KEY_TOKEN_LEN1);
160 }
161
162 return S_OK;
163 }
164
165 //---------------------------------------------------------------------------------------------
166 HRESULT PublicKeyToken::Initialize(
167 PublicKey const & pk)
168 {
169 LIMITED_METHOD_CONTRACT;
170
171 StrongNameBufferHolder<BYTE> pbKeyToken;
172 DWORD cbKeyToken;
173
174 if (!StrongNameTokenFromPublicKey(const_cast<BYTE*>(pk.GetKey()), pk.GetSize(), &pbKeyToken, &cbKeyToken))
175 {
176 return static_cast<HRESULT>(StrongNameErrorInfo());
177 }
178
179 return Initialize(pbKeyToken, cbKeyToken);
180 }
181
182 //=====================================================================================================================
183 HRESULT PublicKeyToken::Initialize(
184 IAssemblyName * pName)
185 {
186 LIMITED_METHOD_CONTRACT;
187
188 HRESULT hr = S_OK;
189
190 DWORD cbKeyToken = sizeof(m_rbKeyToken);
191 hr = pName->GetProperty(ASM_NAME_PUBLIC_KEY_TOKEN, m_rbKeyToken, &cbKeyToken);
192 if (SUCCEEDED(hr))
193 {
194 m_cbKeyToken = cbKeyToken;
195 }
196
197 if (hr == FUSION_E_INVALID_NAME)
198 {
199 hr = S_FALSE;
200 }
201
202 return hr;
203 }
204
205 //=====================================================================================================================
206 HRESULT PublicKeyToken::Initialize(
207 ICLRPrivAssemblyInfo * pName)
208 {
209 LIMITED_METHOD_CONTRACT;
210
211 HRESULT hr = S_OK;
212
213 PublicKey pk;
214 IfFailRet(pk.Initialize(pName));
215
216 if (hr == S_OK) // Can return S_FALSE if no public key/token defined.
217 {
218 hr = Initialize(pk);
219 }
220
221 return hr;
222 }
223
224 //=====================================================================================================================
225 bool operator==(
226 PublicKeyToken const & lhs,
227 PublicKeyToken const & rhs)
228 {
229 LIMITED_METHOD_CONTRACT;
230
231 // Sizes must match
232 if (lhs.GetSize() != rhs.GetSize())
233 {
234 return false;
235 }
236
237 // Empty PKT values are considered to be equal.
238 if (lhs.GetSize() == 0)
239 {
240 return true;
241 }
242
243 // Compare values.
244 return memcmp(lhs.GetToken(), rhs.GetToken(), lhs.GetSize()) == 0;
245 }
246
247 //=====================================================================================================================
248 HRESULT AssemblyIdentity::Initialize(
249 LPCWSTR wzName)
250 {
251 LIMITED_METHOD_CONTRACT;
252 return StringCchCopy(Name, sizeof(Name) / sizeof(Name[0]), wzName);
253 }
254
255 //=====================================================================================================================
256 HRESULT AssemblyIdentity::Initialize(
257 ICLRPrivAssemblyInfo * pAssemblyInfo)
258 {
259 STANDARD_BIND_CONTRACT;
260 HRESULT hr = S_OK;
261
262 DWORD cchName = sizeof(Name) / sizeof(Name[0]);
263 IfFailRet(pAssemblyInfo->GetAssemblyName(cchName, &cchName, Name));
264 IfFailRet(Version.Initialize(pAssemblyInfo));
265 IfFailRet(KeyToken.Initialize(pAssemblyInfo));
266
267 return hr;
268 }
269
270 //=====================================================================================================================
271 HRESULT AssemblyIdentity::Initialize(
272 IAssemblyName * pAssemblyName)
273 {
274 STANDARD_BIND_CONTRACT;
275 HRESULT hr = S_OK;
276
277 DWORD cchName = sizeof(Name) / sizeof(Name[0]);
278 IfFailRet(pAssemblyName->GetName(&cchName, Name));
279 IfFailRet(Version.Initialize(pAssemblyName));
280 IfFailRet(KeyToken.Initialize(pAssemblyName));
281
282 return hr;
283 }
284
285
286
287 //=====================================================================================================================
288 // Destroys list of strings (code:WStringList).
289 void
290 WStringList_Delete(
291 WStringList * pList)
292 {
293 LIMITED_METHOD_CONTRACT;
294
295 if (pList != nullptr)
296 {
297 for (WStringListElem * pElem = pList->RemoveHead(); pElem != nullptr; pElem = pList->RemoveHead())
298 {
299 // Delete the string
300 delete [] pElem->GetValue();
301 delete pElem;
302 }
303
304 delete pList;
305 }
306 }
307
308
309////////////////////////////////////////////////////////////////////////////////////////////////////
310///// ----------------------------- Direct calls to VM -------------------------------------------
311////////////////////////////////////////////////////////////////////////////////////////////////////
312} // namespace CLRPrivBinderUtil
313