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 | // BaseAssemblySpec.cpp |
7 | // |
8 | // Implements the BaseAssemblySpec class |
9 | // |
10 | |
11 | |
12 | // ============================================================ |
13 | |
14 | #include "common.h" |
15 | #include "thekey.h" |
16 | |
17 | VOID BaseAssemblySpec::CloneFieldsToStackingAllocator( StackingAllocator* alloc) |
18 | { |
19 | CONTRACTL |
20 | { |
21 | INSTANCE_CHECK; |
22 | THROWS; |
23 | GC_TRIGGERS; |
24 | MODE_ANY; |
25 | INJECT_FAULT(ThrowOutOfMemory();); |
26 | } |
27 | CONTRACTL_END |
28 | |
29 | #if _DEBUG |
30 | DWORD hash = Hash(); |
31 | #endif |
32 | |
33 | if ((~m_ownedFlags & NAME_OWNED) && |
34 | m_pAssemblyName) { |
35 | S_UINT32 len = S_UINT32((DWORD) strlen(m_pAssemblyName)) + S_UINT32(1); |
36 | if(len.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW); |
37 | LPSTR temp = (LPSTR)alloc->Alloc(len); |
38 | strcpy_s(temp, len.Value(), m_pAssemblyName); |
39 | m_pAssemblyName = temp; |
40 | } |
41 | |
42 | if ((~m_ownedFlags & PUBLIC_KEY_OR_TOKEN_OWNED) && |
43 | m_pbPublicKeyOrToken && m_cbPublicKeyOrToken > 0) { |
44 | BYTE *temp = (BYTE *)alloc->Alloc(S_UINT32(m_cbPublicKeyOrToken)) ; |
45 | memcpy(temp, m_pbPublicKeyOrToken, m_cbPublicKeyOrToken); |
46 | m_pbPublicKeyOrToken = temp; |
47 | } |
48 | |
49 | if ((~m_ownedFlags & LOCALE_OWNED) && |
50 | m_context.szLocale) { |
51 | S_UINT32 len = S_UINT32((DWORD) strlen(m_context.szLocale)) + S_UINT32(1); |
52 | if(len.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW); |
53 | LPSTR temp = (char *)alloc->Alloc(len) ; |
54 | strcpy_s(temp, len.Value(), m_context.szLocale); |
55 | m_context.szLocale = temp; |
56 | } |
57 | |
58 | if ((~m_ownedFlags & CODEBASE_OWNED) && |
59 | m_wszCodeBase) { |
60 | S_UINT32 len = S_UINT32((DWORD) wcslen(m_wszCodeBase)) + S_UINT32(1); |
61 | if(len.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW); |
62 | LPWSTR temp = (LPWSTR)alloc->Alloc(len*S_UINT32(sizeof(WCHAR))); |
63 | wcscpy_s(temp, len.Value(), m_wszCodeBase); |
64 | m_wszCodeBase = temp; |
65 | } |
66 | |
67 | if ((~m_ownedFlags & WINRT_TYPE_NAME_OWNED)) { |
68 | if (m_szWinRtTypeNamespace) |
69 | { |
70 | S_UINT32 len = S_UINT32((DWORD) strlen(m_szWinRtTypeNamespace)) + S_UINT32(1); |
71 | if(len.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW); |
72 | LPSTR temp = (LPSTR)alloc->Alloc(len*S_UINT32(sizeof(CHAR))); |
73 | strcpy_s(temp, len.Value(), m_szWinRtTypeNamespace); |
74 | m_szWinRtTypeNamespace = temp; |
75 | } |
76 | |
77 | if (m_szWinRtTypeClassName) |
78 | { |
79 | S_UINT32 len = S_UINT32((DWORD) strlen(m_szWinRtTypeClassName)) + S_UINT32(1); |
80 | if(len.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW); |
81 | LPSTR temp = (LPSTR)alloc->Alloc(len*S_UINT32(sizeof(CHAR))); |
82 | strcpy_s(temp, len.Value(), m_szWinRtTypeClassName); |
83 | m_szWinRtTypeClassName = temp; |
84 | } |
85 | } |
86 | |
87 | _ASSERTE(hash == Hash()); |
88 | |
89 | } |
90 | |
91 | #ifndef DACCESS_COMPILE |
92 | BOOL BaseAssemblySpec::IsMscorlib() |
93 | { |
94 | CONTRACTL |
95 | { |
96 | THROWS; |
97 | INSTANCE_CHECK; |
98 | GC_TRIGGERS; |
99 | MODE_ANY; |
100 | INJECT_FAULT(COMPlusThrowOM();); |
101 | } |
102 | CONTRACTL_END; |
103 | if (m_pAssemblyName == NULL) |
104 | { |
105 | LPCWSTR file = GetCodeBase(); |
106 | if (file) |
107 | { |
108 | StackSString path(file); |
109 | PEAssembly::UrlToPath(path); |
110 | return SystemDomain::System()->IsBaseLibrary(path); |
111 | } |
112 | return FALSE; |
113 | } |
114 | |
115 | _ASSERTE(strlen(g_psBaseLibraryName) == CoreLibNameLen); |
116 | |
117 | // <TODO>More of bug 213471</TODO> |
118 | size_t iNameLen = strlen(m_pAssemblyName); |
119 | return ( (iNameLen >= CoreLibNameLen) && |
120 | ( (!stricmpUTF8(m_pAssemblyName, g_psBaseLibrary)) || |
121 | ( (!SString::_strnicmp(m_pAssemblyName, g_psBaseLibraryName, CoreLibNameLen)) && |
122 | ( (iNameLen == CoreLibNameLen) || (m_pAssemblyName[CoreLibNameLen] == ',') ) ) ) ); |
123 | } |
124 | |
125 | BOOL BaseAssemblySpec::IsAssemblySpecForMscorlib() |
126 | { |
127 | CONTRACTL |
128 | { |
129 | NOTHROW; |
130 | INSTANCE_CHECK; |
131 | GC_NOTRIGGER; |
132 | MODE_ANY; |
133 | PRECONDITION(strlen(g_psBaseLibraryName) == CoreLibNameLen); |
134 | } |
135 | CONTRACTL_END; |
136 | |
137 | BOOL fIsAssemblySpecForMscorlib = FALSE; |
138 | |
139 | if (m_pAssemblyName) |
140 | { |
141 | size_t iNameLen = strlen(m_pAssemblyName); |
142 | fIsAssemblySpecForMscorlib = ( (iNameLen >= CoreLibNameLen) && |
143 | ( (!_stricmp(m_pAssemblyName, g_psBaseLibrary)) || |
144 | ( (!_strnicmp(m_pAssemblyName, g_psBaseLibraryName, CoreLibNameLen)) && |
145 | ( (iNameLen == CoreLibNameLen) || (m_pAssemblyName[CoreLibNameLen] == ',') ) ) ) ); |
146 | } |
147 | |
148 | return fIsAssemblySpecForMscorlib; |
149 | } |
150 | |
151 | #define MSCORLIB_PUBLICKEY g_rbTheSilverlightPlatformKey |
152 | |
153 | |
154 | // A satellite assembly for mscorlib is named "mscorlib.resources" or |
155 | // mscorlib.debug.resources.dll and uses the same public key as mscorlib. |
156 | // It does not necessarily have the same version, and the Culture will |
157 | // always be set to something like "jp-JP". |
158 | BOOL BaseAssemblySpec::IsMscorlibSatellite() |
159 | { |
160 | CONTRACTL |
161 | { |
162 | THROWS; |
163 | INSTANCE_CHECK; |
164 | GC_TRIGGERS; |
165 | MODE_ANY; |
166 | INJECT_FAULT(COMPlusThrowOM();); |
167 | } |
168 | CONTRACTL_END; |
169 | |
170 | if (m_pAssemblyName == NULL) |
171 | { |
172 | LPCWSTR file = GetCodeBase(); |
173 | if (file) |
174 | { |
175 | StackSString path(file); |
176 | PEAssembly::UrlToPath(path); |
177 | return SystemDomain::System()->IsBaseLibrarySatellite(path); |
178 | } |
179 | return FALSE; |
180 | } |
181 | |
182 | _ASSERTE(strlen(g_psBaseLibrarySatelliteAssemblyName) == CoreLibSatelliteNameLen); |
183 | |
184 | // <TODO>More of bug 213471</TODO> |
185 | size_t iNameLen = strlen(m_pAssemblyName); |
186 | |
187 | // we allow name to be of the form mscorlib.resources.dll only |
188 | BOOL r = ( (m_cbPublicKeyOrToken == sizeof(MSCORLIB_PUBLICKEY)) && |
189 | (iNameLen >= CoreLibSatelliteNameLen) && |
190 | (!SString::_strnicmp(m_pAssemblyName, g_psBaseLibrarySatelliteAssemblyName, CoreLibSatelliteNameLen)) && |
191 | ( (iNameLen == CoreLibSatelliteNameLen) || (m_pAssemblyName[CoreLibSatelliteNameLen] == ',') ) ); |
192 | |
193 | r = r && ( memcmp(m_pbPublicKeyOrToken,MSCORLIB_PUBLICKEY,sizeof(MSCORLIB_PUBLICKEY)) == 0); |
194 | |
195 | return r; |
196 | } |
197 | |
198 | VOID BaseAssemblySpec::ConvertPublicKeyToToken() |
199 | { |
200 | CONTRACTL |
201 | { |
202 | INSTANCE_CHECK; |
203 | THROWS; |
204 | GC_NOTRIGGER; |
205 | MODE_ANY; |
206 | PRECONDITION(HasPublicKey()); |
207 | } |
208 | CONTRACTL_END; |
209 | |
210 | StrongNameBufferHolder<BYTE> pbPublicKeyToken; |
211 | DWORD cbPublicKeyToken; |
212 | if (!StrongNameTokenFromPublicKey(m_pbPublicKeyOrToken, |
213 | m_cbPublicKeyOrToken, |
214 | &pbPublicKeyToken, |
215 | &cbPublicKeyToken)) |
216 | ThrowHR(StrongNameErrorInfo()); |
217 | |
218 | BYTE *temp = new BYTE [cbPublicKeyToken]; |
219 | memcpy(temp, pbPublicKeyToken, cbPublicKeyToken); |
220 | |
221 | if (m_ownedFlags & PUBLIC_KEY_OR_TOKEN_OWNED) |
222 | delete [] m_pbPublicKeyOrToken; |
223 | else |
224 | m_ownedFlags |= PUBLIC_KEY_OR_TOKEN_OWNED; |
225 | |
226 | m_pbPublicKeyOrToken = temp; |
227 | m_cbPublicKeyOrToken = cbPublicKeyToken; |
228 | m_dwFlags &= ~afPublicKey; |
229 | } |
230 | |
231 | // Similar to BaseAssemblySpec::CompareEx, but allows the ref to be partially specified |
232 | // Returns TRUE if ref matches def, FALSE otherwise. |
233 | // |
234 | // static |
235 | BOOL BaseAssemblySpec::CompareRefToDef(const BaseAssemblySpec *pRef, const BaseAssemblySpec *pDef) |
236 | { |
237 | WRAPPER_NO_CONTRACT; |
238 | |
239 | if(pRef->m_wszCodeBase || pDef->m_wszCodeBase) |
240 | { |
241 | if(!pRef->m_wszCodeBase || !pDef->m_wszCodeBase) |
242 | return FALSE; |
243 | |
244 | return wcscmp(pRef->m_wszCodeBase,(pDef->m_wszCodeBase)) == 0; |
245 | } |
246 | |
247 | // Compare fields |
248 | |
249 | // |
250 | // name is non-optional |
251 | // |
252 | if (pRef->m_pAssemblyName != pDef->m_pAssemblyName |
253 | && (pRef->m_pAssemblyName == NULL || pDef->m_pAssemblyName == NULL |
254 | || CompareStrings(pRef->m_pAssemblyName, pDef->m_pAssemblyName))) |
255 | { |
256 | return FALSE; |
257 | } |
258 | |
259 | // |
260 | // public key [token] is non-optional |
261 | // |
262 | if (pRef->m_cbPublicKeyOrToken != pDef->m_cbPublicKeyOrToken |
263 | || memcmp(pRef->m_pbPublicKeyOrToken, pDef->m_pbPublicKeyOrToken, pRef->m_cbPublicKeyOrToken)) |
264 | { |
265 | return FALSE; |
266 | } |
267 | |
268 | // |
269 | // flags are non-optional, except processor architecture, content type, and debuggable attribute bits |
270 | // |
271 | DWORD dwFlagsMask = ~(afPA_FullMask | afContentType_Mask | afDebuggableAttributeMask); |
272 | if ((pRef->m_dwFlags & dwFlagsMask) != (pDef->m_dwFlags & dwFlagsMask)) |
273 | return FALSE; |
274 | |
275 | // To match Fusion behavior, we ignore processor architecture (GetAssemblyNameRefFromMDImport |
276 | // does not look at architecture part of the flags, and having processor architecture in |
277 | // InternalsVisibleTo attribute causess META_E_CA_BAD_FRIENDS_ARGS exception). |
278 | // Content type is optional in pRef. |
279 | if (!IsAfContentType_Default(pRef->m_dwFlags) && (pRef->m_dwFlags & afContentType_Mask) != (pDef->m_dwFlags & afContentType_Mask)) |
280 | return FALSE; |
281 | |
282 | |
283 | // |
284 | // version info is optional in the ref |
285 | // |
286 | if (pRef->m_context.usMajorVersion != (USHORT) -1) |
287 | { |
288 | if (pRef->m_context.usMajorVersion != pDef->m_context.usMajorVersion) |
289 | return FALSE; |
290 | |
291 | if (pRef->m_context.usMinorVersion != (USHORT) -1) |
292 | { |
293 | if (pRef->m_context.usMinorVersion != pDef->m_context.usMinorVersion) |
294 | return FALSE; |
295 | |
296 | if (pRef->m_context.usBuildNumber != (USHORT) -1) |
297 | { |
298 | if (pRef->m_context.usBuildNumber != pDef->m_context.usBuildNumber) |
299 | return FALSE; |
300 | |
301 | if (pRef->m_context.usRevisionNumber != (USHORT) -1) |
302 | { |
303 | if (pRef->m_context.usRevisionNumber != pDef->m_context.usRevisionNumber) |
304 | return FALSE; |
305 | } |
306 | } |
307 | } |
308 | } |
309 | |
310 | // |
311 | // locale info is optional in the ref |
312 | // |
313 | if ((pRef->m_context.szLocale != NULL) |
314 | && (pRef->m_context.szLocale != pDef->m_context.szLocale) |
315 | && strcmp(pRef->m_context.szLocale, pDef->m_context.szLocale)) |
316 | { |
317 | return FALSE; |
318 | } |
319 | |
320 | return TRUE; |
321 | } |
322 | |
323 | // static |
324 | BOOL BaseAssemblySpec::RefMatchesDef(const BaseAssemblySpec* pRef, const BaseAssemblySpec* pDef) |
325 | { |
326 | CONTRACTL |
327 | { |
328 | THROWS; |
329 | GC_NOTRIGGER; |
330 | MODE_ANY; |
331 | PRECONDITION(pRef->GetName()!=NULL && pDef->GetName()!=NULL); |
332 | } |
333 | CONTRACTL_END; |
334 | |
335 | if (pRef->IsStrongNamed()) |
336 | { |
337 | if (!pDef->IsStrongNamed()) |
338 | return FALSE; |
339 | |
340 | if(pRef->HasPublicKey()) |
341 | { |
342 | // cannot use pRef->CompareEx(pDef) here because it does a full comparison |
343 | // and the ref may be partial. |
344 | return CompareRefToDef(pRef, pDef); |
345 | } |
346 | else |
347 | { |
348 | BaseAssemblySpec defCopy; |
349 | defCopy.CopyFrom(pDef); |
350 | defCopy.ConvertPublicKeyToToken(); |
351 | |
352 | return CompareRefToDef(pRef, &defCopy); |
353 | } |
354 | } |
355 | else |
356 | { |
357 | return (CompareStrings(pRef->GetName(), pDef->GetName())==0); |
358 | } |
359 | } |
360 | |
361 | //=========================================================================================== |
362 | // This function may embed additional information, if required. |
363 | // |
364 | // For WinRT (ContentType=WindowsRuntime) assembly specs, this will embed the type name in |
365 | // the IAssemblyName's ASM_NAME_NAME property; otherwise this just creates an IAssemblyName |
366 | // for the provided assembly spec. |
367 | |
368 | void BaseAssemblySpec::GetEncodedName(SString & ssEncodedName) const |
369 | { |
370 | CONTRACTL { |
371 | THROWS; |
372 | GC_NOTRIGGER; |
373 | MODE_ANY; |
374 | } CONTRACTL_END |
375 | |
376 | #ifdef FEATURE_COMINTEROP |
377 | if (IsContentType_WindowsRuntime() && GetWinRtTypeClassName() != NULL) |
378 | { |
379 | ssEncodedName.SetUTF8(GetName()); |
380 | ssEncodedName.Append(SL(W("!" ))); |
381 | if (GetWinRtTypeNamespace() != NULL) |
382 | { |
383 | ssEncodedName.AppendUTF8(GetWinRtTypeNamespace()); |
384 | ssEncodedName.Append(SL(W("." ))); |
385 | } |
386 | ssEncodedName.AppendUTF8(GetWinRtTypeClassName()); |
387 | } |
388 | else |
389 | #endif |
390 | { |
391 | ssEncodedName.SetUTF8(m_pAssemblyName); |
392 | } |
393 | } |
394 | |
395 | VOID BaseAssemblySpec::SetName(SString const & ssName) |
396 | { |
397 | CONTRACTL |
398 | { |
399 | INSTANCE_CHECK; |
400 | GC_NOTRIGGER; |
401 | THROWS; |
402 | } |
403 | CONTRACTL_END; |
404 | |
405 | if (m_ownedFlags & NAME_OWNED) |
406 | { |
407 | delete [] m_pAssemblyName; |
408 | m_ownedFlags &= ~NAME_OWNED; |
409 | } |
410 | |
411 | m_pAssemblyName = NULL; |
412 | |
413 | IfFailThrow(FString::ConvertUnicode_Utf8(ssName.GetUnicode(), & ((LPSTR &) m_pAssemblyName))); |
414 | |
415 | m_ownedFlags |= NAME_OWNED; |
416 | } |
417 | |
418 | HRESULT BaseAssemblySpec::Init(IAssemblyName *pName) |
419 | { |
420 | CONTRACTL |
421 | { |
422 | NOTHROW; |
423 | GC_NOTRIGGER; |
424 | MODE_ANY; |
425 | } |
426 | CONTRACTL_END; |
427 | |
428 | _ASSERTE(pName); |
429 | |
430 | HRESULT hr; |
431 | |
432 | // Fill out info from name, if we have it. |
433 | |
434 | DWORD cbSize = 0; |
435 | hr=pName->GetProperty(ASM_NAME_NAME, NULL, &cbSize); |
436 | if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) { |
437 | hr=S_OK; |
438 | CQuickBytes qb; |
439 | LPWSTR pwName = (LPWSTR) qb.AllocNoThrow(cbSize); |
440 | if (!pwName) |
441 | return E_OUTOFMEMORY; |
442 | |
443 | IfFailRet(pName->GetProperty(ASM_NAME_NAME, pwName, &cbSize)); |
444 | |
445 | m_pAssemblyName = NULL; |
446 | |
447 | hr = FString::ConvertUnicode_Utf8(pwName, & ((LPSTR &) m_pAssemblyName)); |
448 | |
449 | if (FAILED(hr)) |
450 | { |
451 | return hr; |
452 | } |
453 | |
454 | m_ownedFlags |= NAME_OWNED; |
455 | } |
456 | IfFailRet(hr); |
457 | |
458 | // Note: cascade checks so we don't set lower priority version #'s if higher ones are missing |
459 | cbSize = sizeof(m_context.usMajorVersion); |
460 | hr=pName->GetProperty(ASM_NAME_MAJOR_VERSION, &m_context.usMajorVersion, &cbSize); |
461 | |
462 | if (hr!=S_OK || !cbSize) |
463 | m_context.usMajorVersion = (USHORT) -1; |
464 | else { |
465 | cbSize = sizeof(m_context.usMinorVersion); |
466 | hr=pName->GetProperty(ASM_NAME_MINOR_VERSION, &m_context.usMinorVersion, &cbSize); |
467 | } |
468 | |
469 | if (hr!=S_OK || !cbSize) |
470 | m_context.usMinorVersion = (USHORT) -1; |
471 | else { |
472 | cbSize = sizeof(m_context.usBuildNumber); |
473 | pName->GetProperty(ASM_NAME_BUILD_NUMBER, &m_context.usBuildNumber, &cbSize); |
474 | } |
475 | |
476 | if (hr!=S_OK || !cbSize) |
477 | m_context.usBuildNumber = (USHORT) -1; |
478 | else { |
479 | cbSize = sizeof(m_context.usRevisionNumber); |
480 | pName->GetProperty(ASM_NAME_REVISION_NUMBER, &m_context.usRevisionNumber, &cbSize); |
481 | } |
482 | |
483 | if (hr!=S_OK || !cbSize) |
484 | m_context.usRevisionNumber = (USHORT) -1; |
485 | |
486 | if (hr==E_INVALIDARG) |
487 | hr=S_FALSE; |
488 | |
489 | IfFailRet(hr); |
490 | |
491 | cbSize = 0; |
492 | hr = pName->GetProperty(ASM_NAME_CULTURE, NULL, &cbSize); |
493 | |
494 | if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) { |
495 | LPWSTR pwName = (LPWSTR) alloca(cbSize); |
496 | IfFailRet(pName->GetProperty(ASM_NAME_CULTURE, pwName, &cbSize)); |
497 | |
498 | hr = FString::ConvertUnicode_Utf8(pwName, & ((LPSTR &) m_context.szLocale)); |
499 | |
500 | m_ownedFlags |= LOCALE_OWNED; |
501 | } |
502 | |
503 | IfFailRet(hr); |
504 | |
505 | m_dwFlags = 0; |
506 | |
507 | cbSize = 0; |
508 | hr=pName->GetProperty(ASM_NAME_PUBLIC_KEY_TOKEN, NULL, &cbSize); |
509 | if (hr== HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) { |
510 | m_pbPublicKeyOrToken = new (nothrow) BYTE[cbSize]; |
511 | if (m_pbPublicKeyOrToken == NULL) |
512 | return E_OUTOFMEMORY; |
513 | m_cbPublicKeyOrToken = cbSize; |
514 | m_ownedFlags |= PUBLIC_KEY_OR_TOKEN_OWNED; |
515 | IfFailRet(pName->GetProperty(ASM_NAME_PUBLIC_KEY_TOKEN, m_pbPublicKeyOrToken, &cbSize)); |
516 | } |
517 | else { |
518 | if (hr!=E_INVALIDARG) |
519 | IfFailRet(hr); |
520 | hr=pName->GetProperty(ASM_NAME_PUBLIC_KEY, NULL, &cbSize); |
521 | if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) { |
522 | hr=S_OK; |
523 | // <TODO>@todo: we need to normalize this into a public key token so |
524 | // comparisons work correctly. But this involves binding to mscorsn.</TODO> |
525 | m_pbPublicKeyOrToken = new (nothrow) BYTE[cbSize]; |
526 | if (m_pbPublicKeyOrToken == NULL) |
527 | return E_OUTOFMEMORY; |
528 | m_cbPublicKeyOrToken = cbSize; |
529 | m_dwFlags |= afPublicKey; |
530 | m_ownedFlags |= PUBLIC_KEY_OR_TOKEN_OWNED; |
531 | IfFailRet(pName->GetProperty(ASM_NAME_PUBLIC_KEY, m_pbPublicKeyOrToken, &cbSize)); |
532 | } |
533 | else { |
534 | IfFailRet(hr); |
535 | hr= pName->GetProperty(ASM_NAME_NULL_PUBLIC_KEY, NULL, &cbSize); |
536 | if (hr!=S_OK) |
537 | hr=pName->GetProperty(ASM_NAME_NULL_PUBLIC_KEY_TOKEN, NULL, &cbSize); |
538 | if ( hr == S_OK ) { |
539 | m_pbPublicKeyOrToken = new (nothrow) BYTE[0]; |
540 | if (m_pbPublicKeyOrToken == NULL) |
541 | return E_OUTOFMEMORY; |
542 | m_cbPublicKeyOrToken = 0; |
543 | m_ownedFlags |= PUBLIC_KEY_OR_TOKEN_OWNED; |
544 | } |
545 | if (hr==E_INVALIDARG) |
546 | hr=S_FALSE; |
547 | IfFailRet(hr); |
548 | |
549 | } |
550 | } |
551 | |
552 | // Recover the afRetargetable flag |
553 | BOOL bRetarget; |
554 | cbSize = sizeof(bRetarget); |
555 | hr = pName->GetProperty(ASM_NAME_RETARGET, &bRetarget, &cbSize); |
556 | if (hr == S_OK && cbSize != 0 && bRetarget) |
557 | m_dwFlags |= afRetargetable; |
558 | |
559 | // Recover the Processor Architecture flags |
560 | PEKIND peKind; |
561 | cbSize = sizeof(PEKIND); |
562 | hr = pName->GetProperty(ASM_NAME_ARCHITECTURE, &peKind, &cbSize); |
563 | if ((hr == S_OK) && (cbSize != 0) && (peKind < (afPA_NoPlatform >> afPA_Shift)) && (peKind >= (afPA_MSIL >> afPA_Shift))) |
564 | m_dwFlags |= (((DWORD)peKind) << afPA_Shift); |
565 | |
566 | cbSize = 0; |
567 | hr=pName->GetProperty(ASM_NAME_CODEBASE_URL, NULL, &cbSize); |
568 | if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) { |
569 | m_wszCodeBase = new (nothrow) WCHAR [ cbSize/sizeof(WCHAR) ]; |
570 | if (m_wszCodeBase == NULL) |
571 | return E_OUTOFMEMORY; |
572 | m_ownedFlags |= CODE_BASE_OWNED; |
573 | IfFailRet(pName->GetProperty(ASM_NAME_CODEBASE_URL, |
574 | (void*)m_wszCodeBase, &cbSize)); |
575 | } |
576 | else |
577 | IfFailRet(hr); |
578 | |
579 | // Recover the Content Type enum |
580 | DWORD dwContentType; |
581 | cbSize = sizeof(dwContentType); |
582 | hr = pName->GetProperty(ASM_NAME_CONTENT_TYPE, &dwContentType, &cbSize); |
583 | if ((hr == S_OK) && (cbSize == sizeof(dwContentType))) |
584 | { |
585 | _ASSERTE((dwContentType == AssemblyContentType_Default) || (dwContentType == AssemblyContentType_WindowsRuntime)); |
586 | if (dwContentType == AssemblyContentType_WindowsRuntime) |
587 | { |
588 | m_dwFlags |= afContentType_WindowsRuntime; |
589 | } |
590 | } |
591 | |
592 | return S_OK; |
593 | } |
594 | |
595 | HRESULT BaseAssemblySpec::CreateFusionName( |
596 | IAssemblyName **ppName, |
597 | BOOL fIncludeCodeBase/*=TRUE*/, |
598 | BOOL fMustBeBindable /*=FALSE*/) const |
599 | { |
600 | CONTRACTL |
601 | { |
602 | NOTHROW; |
603 | GC_NOTRIGGER; |
604 | MODE_ANY; |
605 | } |
606 | CONTRACTL_END; |
607 | |
608 | HRESULT hr = S_OK; |
609 | |
610 | EX_TRY |
611 | { |
612 | IAssemblyName *pFusionAssemblyName = NULL; |
613 | LPWSTR pwLocale = NULL; |
614 | CQuickBytes qb; |
615 | |
616 | NonVMComHolder< IAssemblyName > holder(NULL); |
617 | |
618 | SmallStackSString ssAssemblyName; |
619 | fMustBeBindable ? GetEncodedName(ssAssemblyName) : GetName(ssAssemblyName); |
620 | |
621 | IfFailGo(CreateAssemblyNameObject(&pFusionAssemblyName, ssAssemblyName.GetUnicode(), 0, NULL)); |
622 | |
623 | holder = pFusionAssemblyName; |
624 | |
625 | if (m_context.usMajorVersion != (USHORT) -1) { |
626 | IfFailGo(pFusionAssemblyName->SetProperty(ASM_NAME_MAJOR_VERSION, |
627 | &m_context.usMajorVersion, |
628 | sizeof(USHORT))); |
629 | |
630 | if (m_context.usMinorVersion != (USHORT) -1) { |
631 | IfFailGo(pFusionAssemblyName->SetProperty(ASM_NAME_MINOR_VERSION, |
632 | &m_context.usMinorVersion, |
633 | sizeof(USHORT))); |
634 | |
635 | if (m_context.usBuildNumber != (USHORT) -1) { |
636 | IfFailGo(pFusionAssemblyName->SetProperty(ASM_NAME_BUILD_NUMBER, |
637 | &m_context.usBuildNumber, |
638 | sizeof(USHORT))); |
639 | |
640 | if (m_context.usRevisionNumber != (USHORT) -1) |
641 | IfFailGo(pFusionAssemblyName->SetProperty(ASM_NAME_REVISION_NUMBER, |
642 | &m_context.usRevisionNumber, |
643 | sizeof(USHORT))); |
644 | } |
645 | } |
646 | } |
647 | |
648 | if (m_context.szLocale) { |
649 | int pwLocaleLen = WszMultiByteToWideChar(CP_UTF8, 0, m_context.szLocale, -1, 0, 0); |
650 | if(pwLocaleLen == 0) { |
651 | IfFailGo(HRESULT_FROM_GetLastError()); |
652 | } else if (pwLocaleLen > MAKE_MAX_LENGTH) { |
653 | IfFailGo(COR_E_OVERFLOW); |
654 | } |
655 | pwLocale = (LPWSTR) qb.AllocNoThrow((pwLocaleLen + 1) *sizeof(WCHAR)); |
656 | if (!pwLocaleLen) |
657 | IfFailGo(E_OUTOFMEMORY); |
658 | if (!WszMultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, |
659 | m_context.szLocale, -1, pwLocale, pwLocaleLen)) |
660 | IfFailGo(HRESULT_FROM_GetLastError()); |
661 | pwLocale[pwLocaleLen] = 0; |
662 | |
663 | IfFailGo(pFusionAssemblyName->SetProperty(ASM_NAME_CULTURE, |
664 | pwLocale, |
665 | (DWORD)(wcslen(pwLocale) + 1) * sizeof (WCHAR))); |
666 | } |
667 | |
668 | if (m_pbPublicKeyOrToken) { |
669 | if (m_cbPublicKeyOrToken) { |
670 | if(m_dwFlags & afPublicKey) { |
671 | IfFailGo(pFusionAssemblyName->SetProperty(ASM_NAME_PUBLIC_KEY, |
672 | m_pbPublicKeyOrToken, m_cbPublicKeyOrToken)); |
673 | } |
674 | else { |
675 | IfFailGo(pFusionAssemblyName->SetProperty(ASM_NAME_PUBLIC_KEY_TOKEN, |
676 | m_pbPublicKeyOrToken, m_cbPublicKeyOrToken)); |
677 | } |
678 | } |
679 | else { |
680 | } |
681 | } |
682 | |
683 | |
684 | // Set the Processor Architecture (if any) |
685 | { |
686 | DWORD dwPEkind = (DWORD)PAIndex(m_dwFlags); |
687 | // Note: Value 0x07 = code:afPA_NoPlatform falls through |
688 | if ((dwPEkind >= peMSIL) && (dwPEkind <= peARM)) |
689 | { |
690 | PEKIND peKind = (PEKIND)dwPEkind; |
691 | IfFailGo(pFusionAssemblyName->SetProperty(ASM_NAME_ARCHITECTURE, |
692 | &peKind, sizeof(peKind))); |
693 | } |
694 | } |
695 | |
696 | // Set the Content Type (if any) |
697 | { |
698 | if (IsAfContentType_WindowsRuntime(m_dwFlags)) |
699 | { |
700 | DWORD dwContentType = AssemblyContentType_WindowsRuntime; |
701 | IfFailGo(pFusionAssemblyName->SetProperty( |
702 | ASM_NAME_CONTENT_TYPE, |
703 | &dwContentType, |
704 | sizeof(dwContentType))); |
705 | } |
706 | } |
707 | |
708 | _ASSERTE(m_wszCodeBase == NULL); |
709 | |
710 | *ppName = pFusionAssemblyName; |
711 | |
712 | holder.SuppressRelease(); |
713 | hr = S_OK; |
714 | |
715 | ErrExit: |
716 | ; |
717 | } |
718 | EX_CATCH_HRESULT(hr); |
719 | |
720 | return hr; |
721 | } |
722 | |
723 | #endif // !DACCESS_COMPILE |
724 | |