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.inl
7//
8
9
10//
11// Implements the BaseAssemblySpec class
12//
13// ============================================================
14
15#ifndef __BASE_ASSEMBLY_SPEC_INL__
16#define __BASE_ASSEMBLY_SPEC_INL__
17
18extern LocaleID g_lcid;
19
20BOOL AreSameBinderInstance(ICLRPrivBinder *pBinderA, ICLRPrivBinder *pBinderB);
21
22inline int BaseAssemblySpec::CompareStrings(LPCUTF8 string1, LPCUTF8 string2)
23{
24 WRAPPER_NO_CONTRACT;
25 SString s1;
26 SString s2;
27 s1.SetUTF8(string1);
28 s2.SetUTF8(string2);
29 return s1.CompareCaseInsensitive(s2,g_lcid);
30}
31
32
33inline BaseAssemblySpec::BaseAssemblySpec()
34{
35 LIMITED_METHOD_CONTRACT;
36 ZeroMemory(this, sizeof(*this));
37 m_context.usMajorVersion = (USHORT) -1;
38 m_context.usMinorVersion = (USHORT) -1;
39 m_context.usBuildNumber = (USHORT) -1;
40 m_context.usRevisionNumber = (USHORT) -1;
41};
42
43inline BaseAssemblySpec::~BaseAssemblySpec()
44{
45 WRAPPER_NO_CONTRACT;
46 if (m_ownedFlags & NAME_OWNED)
47 delete [] m_pAssemblyName;
48 if (m_ownedFlags & PUBLIC_KEY_OR_TOKEN_OWNED)
49 delete [] m_pbPublicKeyOrToken;
50 if (m_wszCodeBase && (m_ownedFlags & CODE_BASE_OWNED))
51 delete [] m_wszCodeBase;
52 if (m_ownedFlags & LOCALE_OWNED)
53 delete [] m_context.szLocale;
54 if (m_szWinRtTypeClassName && (m_ownedFlags & WINRT_TYPE_NAME_OWNED))
55 delete [] m_szWinRtTypeClassName;
56 if (m_szWinRtTypeNamespace && (m_ownedFlags & WINRT_TYPE_NAME_OWNED))
57 delete [] m_szWinRtTypeNamespace;
58}
59
60inline HRESULT BaseAssemblySpec::Init(LPCSTR pAssemblyName,
61 const AssemblyMetaDataInternal* pContext,
62 const BYTE * pbPublicKeyOrToken, DWORD cbPublicKeyOrToken,
63 DWORD dwFlags)
64{
65 LIMITED_METHOD_CONTRACT;
66
67 _ASSERTE(pContext);
68
69 m_pAssemblyName = pAssemblyName;
70 m_pbPublicKeyOrToken = const_cast<BYTE *>(pbPublicKeyOrToken);
71 m_cbPublicKeyOrToken = cbPublicKeyOrToken;
72 m_dwFlags = dwFlags;
73 m_ownedFlags = 0;
74
75 m_context = *pContext;
76
77 return S_OK;
78}
79
80inline HRESULT BaseAssemblySpec::Init(LPCSTR pAssemblyDisplayName)
81{
82 WRAPPER_NO_CONTRACT;
83 m_pAssemblyName = pAssemblyDisplayName;
84 // We eagerly parse the name to allow FusionBind::Hash to avoid throwing.
85 return ParseName();
86}
87
88inline VOID BaseAssemblySpec::CloneFields(int ownedFlags)
89{
90 CONTRACTL
91 {
92 THROWS;
93 GC_NOTRIGGER;
94 MODE_ANY;
95 INJECT_FAULT(ThrowOutOfMemory(););
96 }
97 CONTRACTL_END
98
99#if _DEBUG
100 DWORD hash = Hash();
101#endif
102
103 if ((~m_ownedFlags & NAME_OWNED) && (ownedFlags & NAME_OWNED) &&
104 m_pAssemblyName) {
105 size_t len = strlen(m_pAssemblyName) + 1;
106 LPSTR temp = new char [len];
107 strcpy_s(temp, len, m_pAssemblyName);
108 m_pAssemblyName = temp;
109 m_ownedFlags |= NAME_OWNED;
110 }
111
112 if ((~m_ownedFlags & PUBLIC_KEY_OR_TOKEN_OWNED) &&
113 (ownedFlags & PUBLIC_KEY_OR_TOKEN_OWNED) && m_pbPublicKeyOrToken) {
114 BYTE *temp = new BYTE [m_cbPublicKeyOrToken];
115 memcpy(temp, m_pbPublicKeyOrToken, m_cbPublicKeyOrToken);
116 m_pbPublicKeyOrToken = temp;
117 m_ownedFlags |= PUBLIC_KEY_OR_TOKEN_OWNED;
118 }
119
120 if ((~m_ownedFlags & LOCALE_OWNED) && (ownedFlags & LOCALE_OWNED) &&
121 m_context.szLocale) {
122 size_t len = strlen(m_context.szLocale) + 1;
123 LPSTR temp = new char [len];
124 strcpy_s(temp, len, m_context.szLocale);
125 m_context.szLocale = temp;
126 m_ownedFlags |= LOCALE_OWNED;
127 }
128
129 if ((~m_ownedFlags & CODEBASE_OWNED) && (ownedFlags & CODEBASE_OWNED) &&
130 m_wszCodeBase) {
131 size_t len = wcslen(m_wszCodeBase) + 1;
132 LPWSTR temp = new WCHAR [len];
133 wcscpy_s(temp, len, m_wszCodeBase);
134 m_wszCodeBase = temp;
135 m_ownedFlags |= CODEBASE_OWNED;
136 }
137
138 if ((~m_ownedFlags & WINRT_TYPE_NAME_OWNED) && (ownedFlags & WINRT_TYPE_NAME_OWNED)) {
139
140 NewArrayHolder<CHAR> nameTemp, namespaceTemp;
141
142 if (m_szWinRtTypeClassName) {
143
144 size_t nameLen = strlen(m_szWinRtTypeClassName) + 1;
145 nameTemp = new CHAR [nameLen];
146 strcpy_s(nameTemp, nameLen, m_szWinRtTypeClassName);
147 }
148
149 if (m_szWinRtTypeNamespace){
150
151 size_t namespaceLen = strlen(m_szWinRtTypeNamespace) + 1;
152 namespaceTemp = new CHAR [namespaceLen];
153 strcpy_s(namespaceTemp, namespaceLen, m_szWinRtTypeNamespace);
154 }
155
156 m_szWinRtTypeClassName = nameTemp.Extract();
157 m_szWinRtTypeNamespace = namespaceTemp.Extract();
158 if (m_szWinRtTypeClassName != NULL || m_szWinRtTypeNamespace != NULL)
159 {
160 m_ownedFlags |= WINRT_TYPE_NAME_OWNED;
161 }
162 }
163
164 _ASSERTE(hash == Hash());
165}
166
167inline VOID BaseAssemblySpec::CloneFieldsToLoaderHeap(int flags, LoaderHeap *pHeap, AllocMemTracker *pamTracker)
168{
169 CONTRACTL
170 {
171 INSTANCE_CHECK;
172 THROWS;
173 GC_TRIGGERS;
174 MODE_ANY;
175 INJECT_FAULT(ThrowOutOfMemory(););
176 }
177 CONTRACTL_END
178
179#if _DEBUG
180 DWORD hash = Hash();
181#endif
182
183 if ((~m_ownedFlags & NAME_OWNED) && (flags &NAME_OWNED) &&
184 m_pAssemblyName) {
185 size_t len = strlen(m_pAssemblyName) + 1;
186 LPSTR temp = (LPSTR)pamTracker->Track( pHeap->AllocMem(S_SIZE_T (len)) );
187 strcpy_s(temp, len, m_pAssemblyName);
188 m_pAssemblyName = temp;
189 }
190
191 if ((~m_ownedFlags & PUBLIC_KEY_OR_TOKEN_OWNED) && (flags &PUBLIC_KEY_OR_TOKEN_OWNED) &&
192 m_pbPublicKeyOrToken && m_cbPublicKeyOrToken > 0) {
193 BYTE *temp = (BYTE *)pamTracker->Track( pHeap->AllocMem(S_SIZE_T (m_cbPublicKeyOrToken)) );
194 memcpy(temp, m_pbPublicKeyOrToken, m_cbPublicKeyOrToken);
195 m_pbPublicKeyOrToken = temp;
196 }
197
198 if ((~m_ownedFlags & LOCALE_OWNED) && (flags &LOCALE_OWNED) &&
199 m_context.szLocale) {
200 size_t len = strlen(m_context.szLocale) + 1;
201 LPSTR temp = (char *)pamTracker->Track( pHeap->AllocMem(S_SIZE_T (len)) );
202 strcpy_s(temp, len, m_context.szLocale);
203 m_context.szLocale = temp;
204 }
205
206 if ((~m_ownedFlags & CODEBASE_OWNED) && (flags &CODEBASE_OWNED) &&
207 m_wszCodeBase) {
208 size_t len = wcslen(m_wszCodeBase) + 1;
209 LPWSTR temp = (LPWSTR)pamTracker->Track( pHeap->AllocMem(S_SIZE_T(len*sizeof(WCHAR))) );
210 wcscpy_s(temp, len, m_wszCodeBase);
211 m_wszCodeBase = temp;
212 }
213
214 if ((~m_ownedFlags & WINRT_TYPE_NAME_OWNED) && (flags & WINRT_TYPE_NAME_OWNED)) {
215 if (m_szWinRtTypeNamespace)
216 {
217 size_t len = strlen(m_szWinRtTypeNamespace) + 1;
218 LPSTR temp = (LPSTR)pamTracker->Track( pHeap->AllocMem(S_SIZE_T(len*sizeof(CHAR))) );
219 strcpy_s(temp, len, m_szWinRtTypeNamespace);
220 m_szWinRtTypeNamespace = temp;
221 }
222
223 if (m_szWinRtTypeClassName)
224 {
225 size_t len = strlen(m_szWinRtTypeClassName) + 1;
226 LPSTR temp = (LPSTR)pamTracker->Track( pHeap->AllocMem(S_SIZE_T(len*sizeof(CHAR))) );
227 strcpy_s(temp, len, m_szWinRtTypeClassName);
228 m_szWinRtTypeClassName = temp;
229 }
230 }
231
232 _ASSERTE(hash == Hash());
233
234}
235
236
237inline void BaseAssemblySpec::CopyFrom(const BaseAssemblySpec *pSpec)
238{
239 CONTRACTL
240 {
241 THROWS;
242 GC_NOTRIGGER;
243 MODE_ANY;
244 INJECT_FAULT(ThrowOutOfMemory(););
245 }
246 CONTRACTL_END
247
248 m_pAssemblyName = pSpec->m_pAssemblyName;
249
250 m_pbPublicKeyOrToken = pSpec->m_pbPublicKeyOrToken;
251 m_cbPublicKeyOrToken = pSpec->m_cbPublicKeyOrToken;
252 m_dwFlags = pSpec->m_dwFlags;
253 m_ownedFlags = 0;
254
255 m_wszCodeBase=pSpec->m_wszCodeBase;
256 m_szWinRtTypeNamespace = pSpec->m_szWinRtTypeNamespace;
257 m_szWinRtTypeClassName = pSpec->m_szWinRtTypeClassName;
258
259 m_context = pSpec->m_context;
260
261 m_pHostBinder = pSpec->m_pHostBinder;
262
263 if ((pSpec->m_ownedFlags & BAD_NAME_OWNED) != 0)
264 {
265 m_ownedFlags |= BAD_NAME_OWNED;
266 }
267
268
269 m_pBindingContext = pSpec->m_pBindingContext;
270
271}
272
273
274inline DWORD BaseAssemblySpec::Hash()
275{
276 CONTRACTL {
277 INSTANCE_CHECK;
278 NOTHROW;
279 GC_NOTRIGGER;
280 MODE_ANY;
281 } CONTRACTL_END;
282
283 if(m_wszCodeBase)
284 return HashString(m_wszCodeBase);
285
286 // Hash fields.
287 DWORD hash = 0;
288
289 if (m_pAssemblyName)
290 hash ^= HashStringA(m_pAssemblyName);
291 hash = _rotl(hash, 4);
292
293 hash ^= HashBytes(m_pbPublicKeyOrToken, m_cbPublicKeyOrToken);
294 hash = _rotl(hash, 4);
295
296 hash ^= m_dwFlags;
297 hash = _rotl(hash, 4);
298
299
300 hash ^= m_context.usMajorVersion;
301 hash = _rotl(hash, 8);
302
303 if (m_context.usMajorVersion != (USHORT) -1) {
304 hash ^= m_context.usMinorVersion;
305 hash = _rotl(hash, 8);
306
307 if (m_context.usMinorVersion != (USHORT) -1) {
308 hash ^= m_context.usBuildNumber;
309 hash = _rotl(hash, 8);
310
311 if (m_context.usBuildNumber != (USHORT) -1) {
312 hash ^= m_context.usRevisionNumber;
313 hash = _rotl(hash, 8);
314 }
315 }
316 }
317
318 if (m_context.szLocale)
319 hash ^= HashStringA(m_context.szLocale);
320 hash = _rotl(hash, 4);
321
322 if (m_szWinRtTypeNamespace)
323 {
324 hash ^= HashStringA(m_szWinRtTypeNamespace);
325 hash = _rotl(hash, 4);
326 }
327
328 if (m_szWinRtTypeClassName)
329 {
330 hash ^= HashStringA(m_szWinRtTypeClassName);
331 hash = _rotl(hash, 4);
332 }
333
334
335 return hash;
336}
337
338
339inline BOOL BaseAssemblySpec::CompareEx(BaseAssemblySpec *pSpec, DWORD dwCompareFlags)
340{
341 WRAPPER_NO_CONTRACT;
342
343
344 if(m_wszCodeBase || pSpec->m_wszCodeBase)
345 {
346 if(!m_wszCodeBase || !pSpec->m_wszCodeBase)
347 return FALSE;
348 return wcscmp(m_wszCodeBase,(pSpec->m_wszCodeBase))==0;
349 }
350
351 // Compare fields
352
353 if (m_pAssemblyName != pSpec->m_pAssemblyName
354 && (m_pAssemblyName == NULL || pSpec->m_pAssemblyName == NULL
355 || strcmp(m_pAssemblyName, pSpec->m_pAssemblyName)))
356 return FALSE;
357
358 if (m_cbPublicKeyOrToken != pSpec->m_cbPublicKeyOrToken
359 || memcmp(m_pbPublicKeyOrToken, pSpec->m_pbPublicKeyOrToken, m_cbPublicKeyOrToken))
360 return FALSE;
361
362
363 if (m_dwFlags != pSpec->m_dwFlags)
364 return FALSE;
365
366 if (m_context.usMajorVersion != pSpec->m_context.usMajorVersion)
367 return FALSE;
368
369 if (m_context.usMajorVersion != (USHORT) -1) {
370 if (m_context.usMinorVersion != pSpec->m_context.usMinorVersion)
371 return FALSE;
372
373 if (m_context.usMinorVersion != (USHORT) -1) {
374 if (m_context.usBuildNumber != pSpec->m_context.usBuildNumber)
375 return FALSE;
376
377 if (m_context.usBuildNumber != (USHORT) -1) {
378 if (m_context.usRevisionNumber != pSpec->m_context.usRevisionNumber)
379 return FALSE;
380 }
381 }
382 }
383
384 if (m_context.szLocale != pSpec->m_context.szLocale
385 && (m_context.szLocale == NULL || pSpec->m_context.szLocale == NULL
386 || strcmp(m_context.szLocale, pSpec->m_context.szLocale)))
387 return FALSE;
388
389
390 // If the assemblySpec contains the binding context, then check if they match.
391 if (!(pSpec->IsAssemblySpecForMscorlib() && IsAssemblySpecForMscorlib()))
392 {
393 if (!AreSameBinderInstance(pSpec->m_pBindingContext, m_pBindingContext))
394 {
395 return FALSE;
396 }
397 }
398
399
400 return TRUE;
401}
402
403
404inline HRESULT BaseAssemblySpec::Init(mdToken kAssemblyToken,
405 IMDInternalImport *pImport)
406{
407 CONTRACTL
408 {
409 NOTHROW;
410 GC_NOTRIGGER;
411 MODE_ANY;
412 }
413 CONTRACTL_END;
414
415 HRESULT hr;
416 if (TypeFromToken(kAssemblyToken) == mdtAssembly) {
417
418 IfFailRet(pImport->GetAssemblyProps(kAssemblyToken,
419 (const void **) &m_pbPublicKeyOrToken,
420 &m_cbPublicKeyOrToken,
421 NULL,
422 &m_pAssemblyName,
423 &m_context,
424 &m_dwFlags));
425
426 if (m_cbPublicKeyOrToken != 0)
427 m_dwFlags |= afPublicKey;
428 }
429 else
430 IfFailRet(pImport->GetAssemblyRefProps(kAssemblyToken,
431 (const void**) &m_pbPublicKeyOrToken,
432 &m_cbPublicKeyOrToken,
433 &m_pAssemblyName,
434 &m_context,
435 NULL,
436 NULL,
437 &m_dwFlags));
438
439 // When m_cbPublicKeyOrToken is 0, a NULL in m_pbPublicKeyOrToken indicates that public key or token
440 // is not specified, while a non-NULL in m_pbPublicKeyOrToken indicates an empty public key (i.e.,
441 // a non-strongnamed assembly). However, the MetaData API puts a random value in m_pbPublicKeyOrToken
442 // when m_cbPublicKeyOrToken is 0. Since AssemblyDef or AssemblyRef can't using partial name, we
443 // always ensure that m_pbPublicKeyOrToken is not NULL.
444 if (m_cbPublicKeyOrToken == 0)
445 m_pbPublicKeyOrToken = (PBYTE)1;
446
447 return S_OK;
448}
449
450inline HRESULT BaseAssemblySpec::Init(mdToken tkAssemblyRef,
451 IMetaDataAssemblyImport *pImport)
452{
453 CONTRACTL
454 {
455 NOTHROW;
456 GC_NOTRIGGER;
457 MODE_ANY;
458 }
459 CONTRACTL_END;
460
461 // Retrieve size of assembly name
462 ASSEMBLYMETADATA sContext;
463 LPWSTR wszAssemblyName=NULL;
464 ZeroMemory(&sContext, sizeof(ASSEMBLYMETADATA));
465 HRESULT hr = S_OK;
466 if(TypeFromToken(tkAssemblyRef) == mdtAssembly)
467 {
468 DWORD cchName;
469 IfFailRet(pImport->GetAssemblyProps(tkAssemblyRef, // [IN] The Assembly for which to get the properties.
470 NULL, // [OUT] Pointer to the public key or token.
471 NULL, // [OUT] Count of bytes in the public key or token.
472 NULL, // [OUT] Hash Algorithm
473 NULL, // [OUT] Buffer to fill with name.
474 NULL, // [IN] Size of buffer in wide chars.
475 &cchName, // [OUT] Actual # of wide chars in name.
476 &sContext, // [OUT] Assembly MetaData.
477 NULL)); // [OUT] Flags.
478
479 // Get the assembly name other naming properties
480 wszAssemblyName = (LPWSTR)_alloca(cchName * sizeof(WCHAR));
481 IfFailRet(pImport->GetAssemblyProps(tkAssemblyRef,
482 (const void **)&m_pbPublicKeyOrToken,
483 &m_cbPublicKeyOrToken,
484 NULL,
485 wszAssemblyName,
486 cchName,
487 &cchName,
488 &sContext,
489 &m_dwFlags));
490 }
491 else if(TypeFromToken(tkAssemblyRef) == mdtAssemblyRef)
492 {
493 DWORD cchName;
494 IfFailRet(pImport->GetAssemblyRefProps(tkAssemblyRef, // [IN] The AssemblyRef for which to get the properties.
495 NULL, // [OUT] Pointer to the public key or token.
496 NULL, // [OUT] Count of bytes in the public key or token.
497 NULL, // [OUT] Buffer to fill with name.
498 NULL, // [IN] Size of buffer in wide chars.
499 &cchName, // [OUT] Actual # of wide chars in name.
500 &sContext, // [OUT] Assembly MetaData.
501 NULL, // [OUT] Hash blob.
502 NULL, // [OUT] Count of bytes in the hash blob.
503 NULL)); // [OUT] Flags.
504
505 // Get the assembly name other naming properties
506 wszAssemblyName = (LPWSTR)_alloca(cchName * sizeof(WCHAR));
507 IfFailRet(pImport->GetAssemblyRefProps(tkAssemblyRef,
508 (const void **)&m_pbPublicKeyOrToken,
509 &m_cbPublicKeyOrToken,
510 wszAssemblyName,
511 cchName,
512 &cchName,
513 &sContext,
514 NULL,
515 NULL,
516 &m_dwFlags));
517 }
518 else
519 {
520 _ASSERTE(false && "unexpected token");
521 }
522 MAKE_UTF8PTR_FROMWIDE_NOTHROW(szAssemblyName,wszAssemblyName);
523 IfNullRet(szAssemblyName);
524 size_t len=strlen(szAssemblyName)+1;
525 NewArrayHolder<char> assemblyName(new(nothrow) char[len]);
526 IfNullRet(assemblyName);
527 strcpy_s(assemblyName,len,szAssemblyName);
528
529 m_pAssemblyName=assemblyName.Extract();
530 m_ownedFlags |= CODEBASE_OWNED;
531 SetContext(&sContext);
532 return S_OK;
533}
534
535inline void BaseAssemblySpec::SetCodeBase(LPCWSTR szCodeBase)
536{
537 CONTRACTL
538 {
539 NOTHROW;
540 GC_NOTRIGGER;
541 MODE_ANY;
542 }
543 CONTRACTL_END;
544
545 if(m_wszCodeBase && (m_ownedFlags & CODEBASE_OWNED))
546 delete m_wszCodeBase;
547 m_ownedFlags &= ~CODEBASE_OWNED;
548 m_wszCodeBase=szCodeBase;
549}
550
551inline LPCWSTR BaseAssemblySpec::GetCodeBase()
552{
553 LIMITED_METHOD_CONTRACT;
554 return m_wszCodeBase;
555}
556
557inline void BaseAssemblySpec::SetName(LPCSTR szName)
558{
559 CONTRACTL
560 {
561 INSTANCE_CHECK;
562 GC_NOTRIGGER;
563 NOTHROW;
564 }
565 CONTRACTL_END;
566
567 if (m_pAssemblyName && (m_ownedFlags & NAME_OWNED))
568 delete [] m_pAssemblyName;
569 m_ownedFlags &= ~NAME_OWNED;
570 m_pAssemblyName = szName;
571}
572
573inline void BaseAssemblySpec::SetCulture(LPCSTR szCulture)
574{
575 LIMITED_METHOD_CONTRACT;
576 if (m_context.szLocale && (m_ownedFlags & LOCALE_OWNED))
577 delete [] m_context.szLocale;
578 m_ownedFlags &= ~LOCALE_OWNED;
579 if (strcmp(szCulture,"neutral")==0)
580 m_context.szLocale="";
581 else
582 m_context.szLocale=szCulture;
583}
584
585inline void BaseAssemblySpec::SetContext(ASSEMBLYMETADATA* assemblyData)
586{
587 LIMITED_METHOD_CONTRACT;
588 m_context.usMajorVersion=assemblyData->usMajorVersion;
589 m_context.usMinorVersion=assemblyData->usMinorVersion;
590 m_context.usBuildNumber=assemblyData->usBuildNumber;
591 m_context.usRevisionNumber=assemblyData->usRevisionNumber;
592 m_context.rProcessor=assemblyData->rProcessor;
593 m_context.ulProcessor=assemblyData->ulProcessor;
594 m_context.rOS=assemblyData->rOS;
595 m_context.ulOS=assemblyData->ulOS;
596 m_context.szLocale="";
597};
598
599inline BOOL BaseAssemblySpec::IsStrongNamed() const
600{
601 LIMITED_METHOD_CONTRACT;
602 return m_cbPublicKeyOrToken;
603}
604
605inline BOOL BaseAssemblySpec::HasPublicKey() const
606{
607 LIMITED_METHOD_CONTRACT;
608 return IsAfPublicKey(m_dwFlags) && m_cbPublicKeyOrToken != 0;
609}
610
611inline BOOL BaseAssemblySpec::HasPublicKeyToken() const
612{
613 LIMITED_METHOD_CONTRACT;
614 return IsAfPublicKeyToken(m_dwFlags) && m_cbPublicKeyOrToken != 0;
615}
616
617inline LPCSTR BaseAssemblySpec::GetName() const
618{
619 LIMITED_METHOD_CONTRACT;
620 return m_pAssemblyName;
621}
622
623
624
625inline BOOL BaseAssemblySpec::VerifyBindingString(LPCWSTR pwStr)
626{
627 WRAPPER_NO_CONTRACT;
628 if (wcschr(pwStr, '\\') ||
629 wcschr(pwStr, '/') ||
630 wcschr(pwStr, ':'))
631 return FALSE;
632
633 return TRUE;
634}
635
636
637#endif // __BASE_ASSEMBLY_SPEC_INL__
638