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.
5 /*============================================================
7 ** Header: AssemblyName.cpp
9 ** Purpose: Implements AssemblyName (loader domain) architecture
15 ===========================================================*/
22 #include "assemblyname.hpp"
28 #include "strongname.h"
31 #ifndef URL_ESCAPE_AS_UTF8
32 #define URL_ESCAPE_AS_UTF8 0x00040000 // Percent-encode all non-ASCII characters as their UTF-8 equivalents.
35 FCIMPL1(Object*, AssemblyNameNative::GetFileInformation, StringObject* filenameUNSAFE)
41 ASSEMBLYNAMEREF result;
46 gc.filename = (STRINGREF) filenameUNSAFE;
48 HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
50 if (gc.filename == NULL)
51 COMPlusThrow(kArgumentNullException, W("ArgumentNull_FileName"));
53 if (gc.filename->GetStringLength() == 0)
54 COMPlusThrow(kArgumentException, W("Argument_EmptyFileName"));
56 gc.result = (ASSEMBLYNAMEREF) AllocateObject(MscorlibBinder::GetClass(CLASS__ASSEMBLY_NAME));
59 ///////////////////////////////////////////////
60 SString sFileName(gc.filename->GetBuffer());
61 PEImageHolder pImage = PEImage::OpenImage(sFileName, MDInternalImport_NoCache);
65 // Allow AssemblyLoadContext.GetAssemblyName for native images on CoreCLR
66 if (pImage->HasNTHeaders() && pImage->HasCorHeader() && pImage->HasNativeHeader())
67 pImage->VerifyIsNIAssembly();
69 pImage->VerifyIsAssembly();
73 Exception *ex = GET_EXCEPTION();
74 EEFileLoadException::Throw(sFileName,ex->GetHR(),ex);
76 EX_END_CATCH_UNREACHABLE;
78 SString sUrl = sFileName;
79 PEAssembly::PathToUrl(sUrl);
82 spec.InitializeSpec(TokenFromRid(mdtAssembly,1),pImage->GetMDImport(),NULL,TRUE);
83 spec.AssemblyNameInit(&gc.result, pImage);
85 HELPER_METHOD_FRAME_END();
86 return OBJECTREFToObject(gc.result);
90 FCIMPL1(Object*, AssemblyNameNative::ToString, Object* refThisUNSAFE)
94 OBJECTREF pObj = NULL;
95 ASSEMBLYNAMEREF pThis = (ASSEMBLYNAMEREF) (OBJECTREF) refThisUNSAFE;
96 HELPER_METHOD_FRAME_BEGIN_RET_1(pThis);
99 COMPlusThrow(kNullReferenceException, W("NullReference_This"));
101 Thread *pThread = GetThread();
103 CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease
106 spec.InitializeSpec(&(pThread->m_MarshalAlloc), (ASSEMBLYNAMEREF*) &pThis, FALSE, FALSE);
109 #ifndef FEATURE_FUSION
110 spec.GetFileOrDisplayName(ASM_DISPLAYF_VERSION |
111 ASM_DISPLAYF_CULTURE |
112 ASM_DISPLAYF_PUBLIC_KEY_TOKEN,
115 spec.GetFileOrDisplayName(0, name);
116 #endif // FEATURE_FUSION
118 pObj = (OBJECTREF) StringObject::NewString(name);
120 HELPER_METHOD_FRAME_END();
121 return OBJECTREFToObject(pObj);
126 FCIMPL1(Object*, AssemblyNameNative::GetPublicKeyToken, Object* refThisUNSAFE)
130 OBJECTREF orOutputArray = NULL;
131 OBJECTREF refThis = (OBJECTREF) refThisUNSAFE;
132 HELPER_METHOD_FRAME_BEGIN_RET_1(refThis);
135 COMPlusThrow(kNullReferenceException, W("NullReference_This"));
137 ASSEMBLYNAMEREF orThis = (ASSEMBLYNAMEREF)refThis;
138 U1ARRAYREF orPublicKey = orThis->GetPublicKey();
140 if (orPublicKey != NULL) {
141 DWORD cb = orPublicKey->GetNumComponents();
142 StrongNameBufferHolder<BYTE> pbToken;
146 BYTE *pbKey = (BYTE*) qb.AllocThrows(cb);
147 memcpy(pbKey, orPublicKey->GetDataPtr(), cb);
151 if (!StrongNameTokenFromPublicKey(pbKey, cb, &pbToken, &cb))
152 COMPlusThrowHR(StrongNameErrorInfo());
156 Security::CopyEncodingToByteArray(pbToken, cb, &orOutputArray);
159 HELPER_METHOD_FRAME_END();
160 return OBJECTREFToObject(orOutputArray);
165 FCIMPL4(void, AssemblyNameNative::Init, Object * refThisUNSAFE, OBJECTREF * pAssemblyRef, CLR_BOOL fForIntrospection, CLR_BOOL fRaiseResolveEvent)
169 ASSEMBLYNAMEREF pThis = (ASSEMBLYNAMEREF) (OBJECTREF) refThisUNSAFE;
172 HELPER_METHOD_FRAME_BEGIN_1(pThis);
174 *pAssemblyRef = NULL;
177 COMPlusThrow(kNullReferenceException, W("NullReference_This"));
179 Thread * pThread = GetThread();
181 CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease
184 hr = spec.InitializeSpec(&(pThread->m_MarshalAlloc), (ASSEMBLYNAMEREF *) &pThis, TRUE, FALSE);
188 spec.AssemblyNameInit(&pThis,NULL);
190 else if ((hr == FUSION_E_INVALID_NAME) && fRaiseResolveEvent)
192 Assembly * pAssembly = GetAppDomain()->RaiseAssemblyResolveEvent(&spec, fForIntrospection, FALSE);
194 if (pAssembly == NULL)
196 EEFileLoadException::Throw(&spec, hr);
200 *((OBJECTREF *) (&(*pAssemblyRef))) = pAssembly->GetExposedObject();
208 HELPER_METHOD_FRAME_END();
212 /// "parse" tells us to parse the simple name of the assembly as if it was the full name
213 /// almost never the right thing to do, but needed for compat
215 FCIMPL3(FC_BOOL_RET, AssemblyNameNative::ReferenceMatchesDefinition, AssemblyNameBaseObject* refUNSAFE, AssemblyNameBaseObject* defUNSAFE, CLR_BOOL fParse)
221 ASSEMBLYNAMEREF pRef;
222 ASSEMBLYNAMEREF pDef;
224 gc.pRef = (ASSEMBLYNAMEREF)ObjectToOBJECTREF (refUNSAFE);
225 gc.pDef = (ASSEMBLYNAMEREF)ObjectToOBJECTREF (defUNSAFE);
228 HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
230 Thread *pThread = GetThread();
232 CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease
235 COMPlusThrow(kArgumentNullException, W("ArgumentNull_AssemblyName"));
237 COMPlusThrow(kArgumentNullException, W("ArgumentNull_AssemblyName"));
239 AssemblySpec refSpec;
240 refSpec.InitializeSpec(&(pThread->m_MarshalAlloc), (ASSEMBLYNAMEREF*) &gc.pRef, fParse, FALSE);
242 AssemblySpec defSpec;
243 defSpec.InitializeSpec(&(pThread->m_MarshalAlloc), (ASSEMBLYNAMEREF*) &gc.pDef, fParse, FALSE);
245 #ifdef FEATURE_FUSION
246 SafeComHolder<IAssemblyName> pRefName (NULL);
247 IfFailThrow(refSpec.CreateFusionName(&pRefName, FALSE));
249 SafeComHolder <IAssemblyName> pDefName (NULL);
250 IfFailThrow(defSpec.CreateFusionName(&pDefName, FALSE));
252 // Order matters: Ref->IsEqual(Def)
253 result = (S_OK == pRefName->IsEqual(pDefName, ASM_CMPF_IL_ALL));
255 result=AssemblySpec::RefMatchesDef(&refSpec,&defSpec);
257 HELPER_METHOD_FRAME_END();
258 FC_RETURN_BOOL(result);