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** Header: AssemblyName.cpp
8**
9** Purpose: Implements AssemblyName (loader domain) architecture
10**
11**
12
13
14**
15===========================================================*/
16
17#include "common.h"
18
19#include <stdlib.h>
20#include <shlwapi.h>
21
22#include "assemblyname.hpp"
23#include "field.h"
24#include "strongname.h"
25#include "eeconfig.h"
26
27#ifndef URL_ESCAPE_AS_UTF8
28#define URL_ESCAPE_AS_UTF8 0x00040000 // Percent-encode all non-ASCII characters as their UTF-8 equivalents.
29#endif
30
31FCIMPL1(Object*, AssemblyNameNative::GetFileInformation, StringObject* filenameUNSAFE)
32{
33 FCALL_CONTRACT;
34
35 struct _gc
36 {
37 ASSEMBLYNAMEREF result;
38 STRINGREF filename;
39 } gc;
40
41 gc.result = NULL;
42 gc.filename = (STRINGREF) filenameUNSAFE;
43
44 HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
45
46 if (gc.filename == NULL)
47 COMPlusThrow(kArgumentNullException, W("ArgumentNull_FileName"));
48
49 if (gc.filename->GetStringLength() == 0)
50 COMPlusThrow(kArgumentException, W("Argument_EmptyFileName"));
51
52 gc.result = (ASSEMBLYNAMEREF) AllocateObject(MscorlibBinder::GetClass(CLASS__ASSEMBLY_NAME));
53
54
55 ///////////////////////////////////////////////
56 SString sFileName(gc.filename->GetBuffer());
57 PEImageHolder pImage = PEImage::OpenImage(sFileName, MDInternalImport_NoCache);
58
59 // Load the temporary image using a flat layout, instead of
60 // waiting for it to happen during HasNTHeaders. This allows us to
61 // get the assembly name for images that contain native code for a
62 // non-native platform.
63 PEImageLayoutHolder pLayout(pImage->GetLayout(PEImageLayout::LAYOUT_FLAT, PEImage::LAYOUT_CREATEIFNEEDED));
64
65 // Allow AssemblyLoadContext.GetAssemblyName for native images on CoreCLR
66 if (pImage->HasNTHeaders() && pImage->HasCorHeader() && pImage->HasNativeHeader())
67 pImage->VerifyIsNIAssembly();
68 else
69 pImage->VerifyIsAssembly();
70
71 AssemblySpec spec;
72 spec.InitializeSpec(TokenFromRid(mdtAssembly,1),pImage->GetMDImport(),NULL);
73 spec.AssemblyNameInit(&gc.result, pImage);
74
75 HELPER_METHOD_FRAME_END();
76 return OBJECTREFToObject(gc.result);
77}
78FCIMPLEND
79
80FCIMPL1(Object*, AssemblyNameNative::ToString, Object* refThisUNSAFE)
81{
82 FCALL_CONTRACT;
83
84 OBJECTREF pObj = NULL;
85 ASSEMBLYNAMEREF pThis = (ASSEMBLYNAMEREF) (OBJECTREF) refThisUNSAFE;
86 HELPER_METHOD_FRAME_BEGIN_RET_1(pThis);
87
88 if (pThis == NULL)
89 COMPlusThrow(kNullReferenceException, W("NullReference_This"));
90
91 Thread *pThread = GetThread();
92
93 CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease
94
95 AssemblySpec spec;
96 spec.InitializeSpec(&(pThread->m_MarshalAlloc), (ASSEMBLYNAMEREF*) &pThis, FALSE);
97
98 StackSString name;
99 spec.GetFileOrDisplayName(ASM_DISPLAYF_VERSION |
100 ASM_DISPLAYF_CULTURE |
101 ASM_DISPLAYF_PUBLIC_KEY_TOKEN,
102 name);
103
104 pObj = (OBJECTREF) StringObject::NewString(name);
105
106 HELPER_METHOD_FRAME_END();
107 return OBJECTREFToObject(pObj);
108}
109FCIMPLEND
110
111
112FCIMPL1(Object*, AssemblyNameNative::GetPublicKeyToken, Object* refThisUNSAFE)
113{
114 FCALL_CONTRACT;
115
116 U1ARRAYREF orOutputArray = NULL;
117 OBJECTREF refThis = (OBJECTREF) refThisUNSAFE;
118 HELPER_METHOD_FRAME_BEGIN_RET_1(refThis);
119
120 if (refThis == NULL)
121 COMPlusThrow(kNullReferenceException, W("NullReference_This"));
122
123 ASSEMBLYNAMEREF orThis = (ASSEMBLYNAMEREF)refThis;
124 U1ARRAYREF orPublicKey = orThis->GetPublicKey();
125
126 if (orPublicKey != NULL) {
127 DWORD cb = orPublicKey->GetNumComponents();
128 StrongNameBufferHolder<BYTE> pbToken;
129
130 if (cb) {
131 CQuickBytes qb;
132 BYTE *pbKey = (BYTE*) qb.AllocThrows(cb);
133 memcpy(pbKey, orPublicKey->GetDataPtr(), cb);
134
135 {
136 GCX_PREEMP();
137 if (!StrongNameTokenFromPublicKey(pbKey, cb, &pbToken, &cb))
138 COMPlusThrowHR(StrongNameErrorInfo());
139 }
140 }
141
142 orOutputArray = (U1ARRAYREF)AllocatePrimitiveArray(ELEMENT_TYPE_U1, cb);
143 memcpyNoGCRefs(orOutputArray->m_Array, pbToken, cb);
144 }
145
146 HELPER_METHOD_FRAME_END();
147 return OBJECTREFToObject(orOutputArray);
148}
149FCIMPLEND
150
151
152FCIMPL3(void, AssemblyNameNative::Init, Object * refThisUNSAFE, OBJECTREF * pAssemblyRef, CLR_BOOL fRaiseResolveEvent)
153{
154 FCALL_CONTRACT;
155
156 ASSEMBLYNAMEREF pThis = (ASSEMBLYNAMEREF) (OBJECTREF) refThisUNSAFE;
157 HRESULT hr = S_OK;
158
159 HELPER_METHOD_FRAME_BEGIN_1(pThis);
160
161 *pAssemblyRef = NULL;
162
163 if (pThis == NULL)
164 COMPlusThrow(kNullReferenceException, W("NullReference_This"));
165
166 Thread * pThread = GetThread();
167
168 CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease
169
170 AssemblySpec spec;
171 hr = spec.InitializeSpec(&(pThread->m_MarshalAlloc), (ASSEMBLYNAMEREF *) &pThis, TRUE);
172
173 if (SUCCEEDED(hr))
174 {
175 spec.AssemblyNameInit(&pThis,NULL);
176 }
177 else if ((hr == FUSION_E_INVALID_NAME) && fRaiseResolveEvent)
178 {
179 Assembly * pAssembly = GetAppDomain()->RaiseAssemblyResolveEvent(&spec);
180
181 if (pAssembly == NULL)
182 {
183 EEFileLoadException::Throw(&spec, hr);
184 }
185 else
186 {
187 *((OBJECTREF *) (&(*pAssemblyRef))) = pAssembly->GetExposedObject();
188 }
189 }
190 else
191 {
192 ThrowHR(hr);
193 }
194
195 HELPER_METHOD_FRAME_END();
196}
197FCIMPLEND
198
199
200