| 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:  AssemblyNative.cpp | 
|---|
| 8 | ** | 
|---|
| 9 | ** Purpose: Implements AssemblyNative (loader domain) architecture | 
|---|
| 10 | ** | 
|---|
| 11 | ** | 
|---|
| 12 |  | 
|---|
| 13 |  | 
|---|
| 14 | ** | 
|---|
| 15 | ===========================================================*/ | 
|---|
| 16 |  | 
|---|
| 17 | #include "common.h" | 
|---|
| 18 |  | 
|---|
| 19 | #include <shlwapi.h> | 
|---|
| 20 | #include <stdlib.h> | 
|---|
| 21 | #include "assemblynative.hpp" | 
|---|
| 22 | #include "dllimport.h" | 
|---|
| 23 | #include "field.h" | 
|---|
| 24 | #include "assemblyname.hpp" | 
|---|
| 25 | #include "eeconfig.h" | 
|---|
| 26 | #include "strongname.h" | 
|---|
| 27 | #include "interoputil.h" | 
|---|
| 28 | #include "frames.h" | 
|---|
| 29 | #include "typeparse.h" | 
|---|
| 30 | #include "stackprobe.h" | 
|---|
| 31 |  | 
|---|
| 32 | #include "appdomainnative.hpp" | 
|---|
| 33 | #include "../binder/inc/clrprivbindercoreclr.h" | 
|---|
| 34 |  | 
|---|
| 35 |  | 
|---|
| 36 |  | 
|---|
| 37 | FCIMPL7(Object*, AssemblyNative::Load, AssemblyNameBaseObject* assemblyNameUNSAFE, | 
|---|
| 38 | StringObject* codeBaseUNSAFE, | 
|---|
| 39 | AssemblyBaseObject* requestingAssemblyUNSAFE, | 
|---|
| 40 | StackCrawlMark* stackMark, | 
|---|
| 41 | ICLRPrivBinder * pPrivHostBinder, | 
|---|
| 42 | CLR_BOOL fThrowOnFileNotFound, | 
|---|
| 43 | INT_PTR ptrLoadContextBinder) | 
|---|
| 44 | { | 
|---|
| 45 | FCALL_CONTRACT; | 
|---|
| 46 |  | 
|---|
| 47 | struct _gc | 
|---|
| 48 | { | 
|---|
| 49 | ASSEMBLYNAMEREF assemblyName; | 
|---|
| 50 | STRINGREF       codeBase; | 
|---|
| 51 | ASSEMBLYREF     requestingAssembly; | 
|---|
| 52 | ASSEMBLYREF     rv; | 
|---|
| 53 | } gc; | 
|---|
| 54 |  | 
|---|
| 55 | gc.assemblyName    = (ASSEMBLYNAMEREF) assemblyNameUNSAFE; | 
|---|
| 56 | gc.codeBase        = (STRINGREF)       codeBaseUNSAFE; | 
|---|
| 57 | gc.requestingAssembly    = (ASSEMBLYREF)     requestingAssemblyUNSAFE; | 
|---|
| 58 | gc.rv              = NULL; | 
|---|
| 59 |  | 
|---|
| 60 | HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); | 
|---|
| 61 |  | 
|---|
| 62 | if (gc.assemblyName == NULL) | 
|---|
| 63 | COMPlusThrow(kArgumentNullException, W( "ArgumentNull_AssemblyName")); | 
|---|
| 64 |  | 
|---|
| 65 | Thread * pThread = GetThread(); | 
|---|
| 66 | CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease | 
|---|
| 67 |  | 
|---|
| 68 | DomainAssembly * pParentAssembly = NULL; | 
|---|
| 69 | Assembly * pRefAssembly = NULL; | 
|---|
| 70 |  | 
|---|
| 71 | if(gc.assemblyName->GetSimpleName() == NULL) | 
|---|
| 72 | { | 
|---|
| 73 | if (gc.codeBase == NULL) | 
|---|
| 74 | COMPlusThrow(kArgumentException, W( "Format_StringZeroLength")); | 
|---|
| 75 | } | 
|---|
| 76 | else | 
|---|
| 77 | { | 
|---|
| 78 | // Compute parent assembly | 
|---|
| 79 | if (gc.requestingAssembly == NULL) | 
|---|
| 80 | { | 
|---|
| 81 | pRefAssembly = SystemDomain::GetCallersAssembly(stackMark); | 
|---|
| 82 | } | 
|---|
| 83 | else | 
|---|
| 84 | { | 
|---|
| 85 | pRefAssembly = gc.requestingAssembly->GetAssembly(); | 
|---|
| 86 | } | 
|---|
| 87 |  | 
|---|
| 88 | // Shared or collectible assemblies should not be used for the parent in the | 
|---|
| 89 | // late-bound case. | 
|---|
| 90 | if (pRefAssembly && (!pRefAssembly->IsCollectible())) | 
|---|
| 91 | { | 
|---|
| 92 | pParentAssembly= pRefAssembly->GetDomainAssembly(); | 
|---|
| 93 | } | 
|---|
| 94 | } | 
|---|
| 95 |  | 
|---|
| 96 | // Initialize spec | 
|---|
| 97 | AssemblySpec spec; | 
|---|
| 98 | spec.InitializeSpec(&(pThread->m_MarshalAlloc), | 
|---|
| 99 | &gc.assemblyName, | 
|---|
| 100 | FALSE); | 
|---|
| 101 |  | 
|---|
| 102 | if (!spec.HasUniqueIdentity()) | 
|---|
| 103 | {   // Insuficient assembly name for binding (e.g. ContentType=WindowsRuntime cannot bind by assembly name) | 
|---|
| 104 | EEFileLoadException::Throw(&spec, COR_E_NOTSUPPORTED); | 
|---|
| 105 | } | 
|---|
| 106 |  | 
|---|
| 107 | if (pPrivHostBinder != NULL) | 
|---|
| 108 | { | 
|---|
| 109 | pParentAssembly = NULL; | 
|---|
| 110 | spec.SetHostBinder(pPrivHostBinder); | 
|---|
| 111 | } | 
|---|
| 112 |  | 
|---|
| 113 | if (gc.codeBase != NULL) | 
|---|
| 114 | spec.SetCodeBase(&(pThread->m_MarshalAlloc), &gc.codeBase); | 
|---|
| 115 |  | 
|---|
| 116 | if (pParentAssembly != NULL) | 
|---|
| 117 | spec.SetParentAssembly(pParentAssembly); | 
|---|
| 118 |  | 
|---|
| 119 | // Have we been passed the reference to the binder against which this load should be triggered? | 
|---|
| 120 | // If so, then use it to set the fallback load context binder. | 
|---|
| 121 | if (ptrLoadContextBinder != NULL) | 
|---|
| 122 | { | 
|---|
| 123 | spec.SetFallbackLoadContextBinderForRequestingAssembly(reinterpret_cast<ICLRPrivBinder *>(ptrLoadContextBinder)); | 
|---|
| 124 | spec.SetPreferFallbackLoadContextBinder(); | 
|---|
| 125 | } | 
|---|
| 126 | else if (pRefAssembly != NULL) | 
|---|
| 127 | { | 
|---|
| 128 | // If the requesting assembly has Fallback LoadContext binder available, | 
|---|
| 129 | // then set it up in the AssemblySpec. | 
|---|
| 130 | PEFile *pRefAssemblyManifestFile = pRefAssembly->GetManifestFile(); | 
|---|
| 131 | spec.SetFallbackLoadContextBinderForRequestingAssembly(pRefAssemblyManifestFile->GetFallbackLoadContextBinder()); | 
|---|
| 132 | } | 
|---|
| 133 |  | 
|---|
| 134 | Assembly *pAssembly; | 
|---|
| 135 |  | 
|---|
| 136 | { | 
|---|
| 137 | GCX_PREEMP(); | 
|---|
| 138 | pAssembly = spec.LoadAssembly(FILE_LOADED, fThrowOnFileNotFound); | 
|---|
| 139 | } | 
|---|
| 140 |  | 
|---|
| 141 | if (pAssembly != NULL) | 
|---|
| 142 | gc.rv = (ASSEMBLYREF) pAssembly->GetExposedObject(); | 
|---|
| 143 |  | 
|---|
| 144 | HELPER_METHOD_FRAME_END(); | 
|---|
| 145 |  | 
|---|
| 146 | return OBJECTREFToObject(gc.rv); | 
|---|
| 147 | } | 
|---|
| 148 | FCIMPLEND | 
|---|
| 149 |  | 
|---|
| 150 | /* static */ | 
|---|
| 151 | Assembly* AssemblyNative::LoadFromPEImage(ICLRPrivBinder* pBinderContext, PEImage *pILImage, PEImage *pNIImage) | 
|---|
| 152 | { | 
|---|
| 153 | CONTRACT(Assembly*) | 
|---|
| 154 | { | 
|---|
| 155 | STANDARD_VM_CHECK; | 
|---|
| 156 | PRECONDITION(CheckPointer(pBinderContext)); | 
|---|
| 157 | POSTCONDITION(CheckPointer(RETVAL)); | 
|---|
| 158 | } | 
|---|
| 159 | CONTRACT_END; | 
|---|
| 160 |  | 
|---|
| 161 | Assembly *pLoadedAssembly = NULL; | 
|---|
| 162 |  | 
|---|
| 163 | ReleaseHolder<ICLRPrivAssembly> pAssembly; | 
|---|
| 164 |  | 
|---|
| 165 | // Get the correct PEImage to work with. | 
|---|
| 166 | BOOL fIsNativeImage = TRUE; | 
|---|
| 167 | PEImage *pImage = pNIImage; | 
|---|
| 168 | if (pNIImage == NULL) | 
|---|
| 169 | { | 
|---|
| 170 | // Since we do not have a NI image, we are working with IL assembly | 
|---|
| 171 | pImage = pILImage; | 
|---|
| 172 | fIsNativeImage = FALSE; | 
|---|
| 173 | } | 
|---|
| 174 | _ASSERTE(pImage != NULL); | 
|---|
| 175 |  | 
|---|
| 176 | BOOL fHadLoadFailure = FALSE; | 
|---|
| 177 |  | 
|---|
| 178 | // Force the image to be loaded and mapped so that subsequent loads do not | 
|---|
| 179 | // map a duplicate copy. | 
|---|
| 180 | if (pImage->IsFile()) | 
|---|
| 181 | { | 
|---|
| 182 | pImage->Load(); | 
|---|
| 183 | } | 
|---|
| 184 | else | 
|---|
| 185 | { | 
|---|
| 186 | pImage->LoadNoFile(); | 
|---|
| 187 | } | 
|---|
| 188 |  | 
|---|
| 189 | DWORD dwMessageID = IDS_EE_FILELOAD_ERROR_GENERIC; | 
|---|
| 190 |  | 
|---|
| 191 | // Set the caller's assembly to be mscorlib | 
|---|
| 192 | DomainAssembly *pCallersAssembly = SystemDomain::System()->SystemAssembly()->GetDomainAssembly(); | 
|---|
| 193 | PEAssembly *pParentAssembly = pCallersAssembly->GetFile(); | 
|---|
| 194 |  | 
|---|
| 195 | // Initialize the AssemblySpec | 
|---|
| 196 | AssemblySpec spec; | 
|---|
| 197 | spec.InitializeSpec(TokenFromRid(1, mdtAssembly), pImage->GetMDImport(), pCallersAssembly); | 
|---|
| 198 | spec.SetBindingContext(pBinderContext); | 
|---|
| 199 |  | 
|---|
| 200 | HRESULT hr = S_OK; | 
|---|
| 201 | PTR_AppDomain pCurDomain = GetAppDomain(); | 
|---|
| 202 | CLRPrivBinderCoreCLR *pTPABinder = pCurDomain->GetTPABinderContext(); | 
|---|
| 203 | if (!AreSameBinderInstance(pTPABinder, pBinderContext)) | 
|---|
| 204 | { | 
|---|
| 205 | // We are working with custom Assembly Load Context so bind the assembly using it. | 
|---|
| 206 | CLRPrivBinderAssemblyLoadContext *pBinder = reinterpret_cast<CLRPrivBinderAssemblyLoadContext *>(pBinderContext); | 
|---|
| 207 | hr = pBinder->BindUsingPEImage(pImage, fIsNativeImage, &pAssembly); | 
|---|
| 208 | } | 
|---|
| 209 | else | 
|---|
| 210 | { | 
|---|
| 211 | // Bind the assembly using TPA binder | 
|---|
| 212 | hr = pTPABinder->BindUsingPEImage(pImage, fIsNativeImage, &pAssembly); | 
|---|
| 213 | } | 
|---|
| 214 |  | 
|---|
| 215 | if (hr != S_OK) | 
|---|
| 216 | { | 
|---|
| 217 | // Give a more specific message for the case when we found the assembly with the same name already loaded. | 
|---|
| 218 | if (hr == COR_E_FILELOAD) | 
|---|
| 219 | { | 
|---|
| 220 | dwMessageID = IDS_HOST_ASSEMBLY_RESOLVER_ASSEMBLY_ALREADY_LOADED_IN_CONTEXT; | 
|---|
| 221 | } | 
|---|
| 222 |  | 
|---|
| 223 | StackSString name; | 
|---|
| 224 | spec.GetFileOrDisplayName(0, name); | 
|---|
| 225 | COMPlusThrowHR(COR_E_FILELOAD, dwMessageID, name); | 
|---|
| 226 | } | 
|---|
| 227 |  | 
|---|
| 228 | BINDER_SPACE::Assembly* assem; | 
|---|
| 229 | assem = BINDER_SPACE::GetAssemblyFromPrivAssemblyFast(pAssembly); | 
|---|
| 230 |  | 
|---|
| 231 | PEAssemblyHolder pPEAssembly(PEAssembly::Open(pParentAssembly, assem->GetPEImage(), assem->GetNativePEImage(), pAssembly)); | 
|---|
| 232 |  | 
|---|
| 233 | DomainAssembly *pDomainAssembly = pCurDomain->LoadDomainAssembly(&spec, pPEAssembly, FILE_LOADED); | 
|---|
| 234 | RETURN pDomainAssembly->GetAssembly(); | 
|---|
| 235 | } | 
|---|
| 236 |  | 
|---|
| 237 | /* static */ | 
|---|
| 238 | void QCALLTYPE AssemblyNative::LoadFromPath(INT_PTR ptrNativeAssemblyLoadContext, LPCWSTR pwzILPath, LPCWSTR pwzNIPath, QCall::ObjectHandleOnStack retLoadedAssembly) | 
|---|
| 239 | { | 
|---|
| 240 | QCALL_CONTRACT; | 
|---|
| 241 |  | 
|---|
| 242 | BEGIN_QCALL; | 
|---|
| 243 |  | 
|---|
| 244 | PTR_AppDomain pCurDomain = GetAppDomain(); | 
|---|
| 245 |  | 
|---|
| 246 | // Get the binder context in which the assembly will be loaded. | 
|---|
| 247 | ICLRPrivBinder *pBinderContext = reinterpret_cast<ICLRPrivBinder*>(ptrNativeAssemblyLoadContext); | 
|---|
| 248 | _ASSERTE(pBinderContext != NULL); | 
|---|
| 249 |  | 
|---|
| 250 | // Form the PEImage for the ILAssembly. Incase of an exception, the holders will ensure | 
|---|
| 251 | // the release of the image. | 
|---|
| 252 | PEImageHolder pILImage, pNIImage; | 
|---|
| 253 |  | 
|---|
| 254 | if (pwzILPath != NULL) | 
|---|
| 255 | { | 
|---|
| 256 | pILImage = PEImage::OpenImage(pwzILPath); | 
|---|
| 257 |  | 
|---|
| 258 | // Need to verify that this is a valid CLR assembly. | 
|---|
| 259 | if (!pILImage->CheckILFormat()) | 
|---|
| 260 | ThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL); | 
|---|
| 261 | } | 
|---|
| 262 |  | 
|---|
| 263 | // Form the PEImage for the NI assembly, if specified | 
|---|
| 264 | if (pwzNIPath != NULL) | 
|---|
| 265 | { | 
|---|
| 266 | pNIImage = PEImage::OpenImage(pwzNIPath, MDInternalImport_TrustedNativeImage); | 
|---|
| 267 |  | 
|---|
| 268 | if (pNIImage->HasReadyToRunHeader()) | 
|---|
| 269 | { | 
|---|
| 270 | // ReadyToRun images are treated as IL images by the rest of the system | 
|---|
| 271 | if (!pNIImage->CheckILFormat()) | 
|---|
| 272 | ThrowHR(COR_E_BADIMAGEFORMAT); | 
|---|
| 273 |  | 
|---|
| 274 | pILImage = pNIImage.Extract(); | 
|---|
| 275 | pNIImage = NULL; | 
|---|
| 276 | } | 
|---|
| 277 | else | 
|---|
| 278 | { | 
|---|
| 279 | if (!pNIImage->CheckNativeFormat()) | 
|---|
| 280 | ThrowHR(COR_E_BADIMAGEFORMAT); | 
|---|
| 281 | } | 
|---|
| 282 | } | 
|---|
| 283 |  | 
|---|
| 284 | Assembly *pLoadedAssembly = AssemblyNative::LoadFromPEImage(pBinderContext, pILImage, pNIImage); | 
|---|
| 285 |  | 
|---|
| 286 | { | 
|---|
| 287 | GCX_COOP(); | 
|---|
| 288 | retLoadedAssembly.Set(pLoadedAssembly->GetExposedObject()); | 
|---|
| 289 | } | 
|---|
| 290 |  | 
|---|
| 291 | LOG((LF_CLASSLOADER, | 
|---|
| 292 | LL_INFO100, | 
|---|
| 293 | "\tLoaded assembly from a file\n")); | 
|---|
| 294 |  | 
|---|
| 295 | END_QCALL; | 
|---|
| 296 | } | 
|---|
| 297 |  | 
|---|
| 298 | // static | 
|---|
| 299 | INT_PTR QCALLTYPE AssemblyNative::InternalLoadUnmanagedDllFromPath(LPCWSTR unmanagedLibraryPath) | 
|---|
| 300 | { | 
|---|
| 301 | QCALL_CONTRACT; | 
|---|
| 302 |  | 
|---|
| 303 | NATIVE_LIBRARY_HANDLE moduleHandle = nullptr; | 
|---|
| 304 |  | 
|---|
| 305 | BEGIN_QCALL; | 
|---|
| 306 |  | 
|---|
| 307 | moduleHandle = NDirect::LoadLibraryFromPath(unmanagedLibraryPath, true); | 
|---|
| 308 |  | 
|---|
| 309 | END_QCALL; | 
|---|
| 310 |  | 
|---|
| 311 | return reinterpret_cast<INT_PTR>(moduleHandle); | 
|---|
| 312 | } | 
|---|
| 313 |  | 
|---|
| 314 | /*static */ | 
|---|
| 315 | void QCALLTYPE AssemblyNative::LoadFromStream(INT_PTR ptrNativeAssemblyLoadContext, INT_PTR ptrAssemblyArray, | 
|---|
| 316 | INT32 cbAssemblyArrayLength, INT_PTR ptrSymbolArray, INT32 cbSymbolArrayLength, | 
|---|
| 317 | QCall::ObjectHandleOnStack retLoadedAssembly) | 
|---|
| 318 | { | 
|---|
| 319 | QCALL_CONTRACT; | 
|---|
| 320 |  | 
|---|
| 321 | BEGIN_QCALL; | 
|---|
| 322 |  | 
|---|
| 323 | // Ensure that the invariants are in place | 
|---|
| 324 | _ASSERTE(ptrNativeAssemblyLoadContext != NULL); | 
|---|
| 325 | _ASSERTE((ptrAssemblyArray != NULL) && (cbAssemblyArrayLength > 0)); | 
|---|
| 326 | _ASSERTE((ptrSymbolArray == NULL) || (cbSymbolArrayLength > 0)); | 
|---|
| 327 |  | 
|---|
| 328 | // We must have a flat image stashed away since we need a private | 
|---|
| 329 | // copy of the data which we can verify before doing the mapping. | 
|---|
| 330 | PVOID pAssemblyArray = reinterpret_cast<PVOID>(ptrAssemblyArray); | 
|---|
| 331 |  | 
|---|
| 332 | PEImageHolder pILImage(PEImage::LoadFlat(pAssemblyArray, (COUNT_T)cbAssemblyArrayLength)); | 
|---|
| 333 |  | 
|---|
| 334 | // Need to verify that this is a valid CLR assembly. | 
|---|
| 335 | if (!pILImage->CheckILFormat()) | 
|---|
| 336 | ThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL); | 
|---|
| 337 |  | 
|---|
| 338 | // Get the binder context in which the assembly will be loaded | 
|---|
| 339 | ICLRPrivBinder *pBinderContext = reinterpret_cast<ICLRPrivBinder*>(ptrNativeAssemblyLoadContext); | 
|---|
| 340 |  | 
|---|
| 341 | // Pass the stream based assembly as IL and NI in an attempt to bind and load it | 
|---|
| 342 | Assembly* pLoadedAssembly = AssemblyNative::LoadFromPEImage(pBinderContext, pILImage, NULL); | 
|---|
| 343 | { | 
|---|
| 344 | GCX_COOP(); | 
|---|
| 345 | retLoadedAssembly.Set(pLoadedAssembly->GetExposedObject()); | 
|---|
| 346 | } | 
|---|
| 347 |  | 
|---|
| 348 | LOG((LF_CLASSLOADER, | 
|---|
| 349 | LL_INFO100, | 
|---|
| 350 | "\tLoaded assembly from a file\n")); | 
|---|
| 351 |  | 
|---|
| 352 | // In order to assign the PDB image (if present), | 
|---|
| 353 | // the resulting assembly's image needs to be exactly the one | 
|---|
| 354 | // we created above. We need pointer comparison instead of pe image equivalence | 
|---|
| 355 | // to avoid mixed binaries/PDB pairs of other images. | 
|---|
| 356 | // This applies to both Desktop CLR and CoreCLR, with or without fusion. | 
|---|
| 357 | BOOL fIsSameAssembly = (pLoadedAssembly->GetManifestFile()->GetILimage() == pILImage); | 
|---|
| 358 |  | 
|---|
| 359 | // Setting the PDB info is only applicable for our original assembly. | 
|---|
| 360 | // This applies to both Desktop CLR and CoreCLR, with or without fusion. | 
|---|
| 361 | if (fIsSameAssembly) | 
|---|
| 362 | { | 
|---|
| 363 | #ifdef DEBUGGING_SUPPORTED | 
|---|
| 364 | // If we were given symbols, save a copy of them. | 
|---|
| 365 | if (ptrSymbolArray != NULL) | 
|---|
| 366 | { | 
|---|
| 367 | PBYTE pSymbolArray = reinterpret_cast<PBYTE>(ptrSymbolArray); | 
|---|
| 368 | pLoadedAssembly->GetManifestModule()->SetSymbolBytes(pSymbolArray, (DWORD)cbSymbolArrayLength); | 
|---|
| 369 | } | 
|---|
| 370 | #endif // DEBUGGING_SUPPORTED | 
|---|
| 371 | } | 
|---|
| 372 |  | 
|---|
| 373 | END_QCALL; | 
|---|
| 374 | } | 
|---|
| 375 |  | 
|---|
| 376 | void QCALLTYPE AssemblyNative::GetLocation(QCall::AssemblyHandle pAssembly, QCall::StringHandleOnStack retString) | 
|---|
| 377 | { | 
|---|
| 378 | QCALL_CONTRACT; | 
|---|
| 379 |  | 
|---|
| 380 | BEGIN_QCALL; | 
|---|
| 381 |  | 
|---|
| 382 | { | 
|---|
| 383 | retString.Set(pAssembly->GetFile()->GetPath()); | 
|---|
| 384 | } | 
|---|
| 385 |  | 
|---|
| 386 | END_QCALL; | 
|---|
| 387 | } | 
|---|
| 388 |  | 
|---|
| 389 | void QCALLTYPE AssemblyNative::GetType(QCall::AssemblyHandle pAssembly, LPCWSTR wszName, BOOL bThrowOnError, BOOL bIgnoreCase, QCall::ObjectHandleOnStack retType, QCall::ObjectHandleOnStack keepAlive) | 
|---|
| 390 | { | 
|---|
| 391 | CONTRACTL | 
|---|
| 392 | { | 
|---|
| 393 | QCALL_CHECK; | 
|---|
| 394 | PRECONDITION(CheckPointer(wszName)); | 
|---|
| 395 | } | 
|---|
| 396 | CONTRACTL_END; | 
|---|
| 397 |  | 
|---|
| 398 | TypeHandle retTypeHandle; | 
|---|
| 399 |  | 
|---|
| 400 | BEGIN_QCALL; | 
|---|
| 401 |  | 
|---|
| 402 | if (!wszName) | 
|---|
| 403 | COMPlusThrowArgumentNull(W( "name"), W( "ArgumentNull_String")); | 
|---|
| 404 |  | 
|---|
| 405 | BOOL prohibitAsmQualifiedName = TRUE; | 
|---|
| 406 |  | 
|---|
| 407 | // Load the class from this assembly (fail if it is in a different one). | 
|---|
| 408 | retTypeHandle = TypeName::GetTypeManaged(wszName, pAssembly, bThrowOnError, bIgnoreCase, prohibitAsmQualifiedName, NULL, FALSE, (OBJECTREF*)keepAlive.m_ppObject); | 
|---|
| 409 |  | 
|---|
| 410 | if (!retTypeHandle.IsNull()) | 
|---|
| 411 | { | 
|---|
| 412 | GCX_COOP(); | 
|---|
| 413 | retType.Set(retTypeHandle.GetManagedClassObject()); | 
|---|
| 414 | } | 
|---|
| 415 |  | 
|---|
| 416 | END_QCALL; | 
|---|
| 417 |  | 
|---|
| 418 | return; | 
|---|
| 419 | } | 
|---|
| 420 |  | 
|---|
| 421 | void QCALLTYPE AssemblyNative::GetForwardedType(QCall::AssemblyHandle pAssembly, mdToken mdtExternalType, QCall::ObjectHandleOnStack retType) | 
|---|
| 422 | { | 
|---|
| 423 | CONTRACTL | 
|---|
| 424 | { | 
|---|
| 425 | QCALL_CHECK; | 
|---|
| 426 | } | 
|---|
| 427 | CONTRACTL_END; | 
|---|
| 428 |  | 
|---|
| 429 | BEGIN_QCALL; | 
|---|
| 430 |  | 
|---|
| 431 | LPCSTR pszNameSpace; | 
|---|
| 432 | LPCSTR pszClassName; | 
|---|
| 433 | mdToken mdImpl; | 
|---|
| 434 |  | 
|---|
| 435 | Assembly * pAsm = pAssembly->GetAssembly(); | 
|---|
| 436 | Module *pManifestModule = pAsm->GetManifestModule(); | 
|---|
| 437 | IfFailThrow(pManifestModule->GetMDImport()->GetExportedTypeProps(mdtExternalType, &pszNameSpace, &pszClassName, &mdImpl, NULL, NULL)); | 
|---|
| 438 | if (TypeFromToken(mdImpl) == mdtAssemblyRef) | 
|---|
| 439 | { | 
|---|
| 440 | NameHandle typeName(pszNameSpace, pszClassName); | 
|---|
| 441 | typeName.SetTypeToken(pManifestModule, mdtExternalType); | 
|---|
| 442 | TypeHandle typeHnd = pAsm->GetLoader()->LoadTypeHandleThrowIfFailed(&typeName); | 
|---|
| 443 | { | 
|---|
| 444 | GCX_COOP(); | 
|---|
| 445 | retType.Set(typeHnd.GetManagedClassObject()); | 
|---|
| 446 | } | 
|---|
| 447 | } | 
|---|
| 448 |  | 
|---|
| 449 | END_QCALL; | 
|---|
| 450 |  | 
|---|
| 451 | return; | 
|---|
| 452 | } | 
|---|
| 453 |  | 
|---|
| 454 | FCIMPL1(FC_BOOL_RET, AssemblyNative::IsDynamic, AssemblyBaseObject* pAssemblyUNSAFE) | 
|---|
| 455 | { | 
|---|
| 456 | FCALL_CONTRACT; | 
|---|
| 457 |  | 
|---|
| 458 | ASSEMBLYREF refAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pAssemblyUNSAFE); | 
|---|
| 459 |  | 
|---|
| 460 | if (refAssembly == NULL) | 
|---|
| 461 | FCThrowRes(kArgumentNullException, W( "Arg_InvalidHandle")); | 
|---|
| 462 |  | 
|---|
| 463 | FC_RETURN_BOOL(refAssembly->GetDomainAssembly()->GetFile()->IsDynamic()); | 
|---|
| 464 | } | 
|---|
| 465 | FCIMPLEND | 
|---|
| 466 |  | 
|---|
| 467 | void QCALLTYPE AssemblyNative::GetVersion(QCall::AssemblyHandle pAssembly, INT32* pMajorVersion, INT32* pMinorVersion, INT32*pBuildNumber, INT32* pRevisionNumber) | 
|---|
| 468 | { | 
|---|
| 469 | QCALL_CONTRACT; | 
|---|
| 470 |  | 
|---|
| 471 | BEGIN_QCALL; | 
|---|
| 472 |  | 
|---|
| 473 | UINT16 major=0xffff, minor=0xffff, build=0xffff, revision=0xffff; | 
|---|
| 474 |  | 
|---|
| 475 | pAssembly->GetFile()->GetVersion(&major, &minor, &build, &revision); | 
|---|
| 476 |  | 
|---|
| 477 | *pMajorVersion = major; | 
|---|
| 478 | *pMinorVersion = minor; | 
|---|
| 479 | *pBuildNumber = build; | 
|---|
| 480 | *pRevisionNumber = revision; | 
|---|
| 481 |  | 
|---|
| 482 | END_QCALL; | 
|---|
| 483 | } | 
|---|
| 484 |  | 
|---|
| 485 | void QCALLTYPE AssemblyNative::GetPublicKey(QCall::AssemblyHandle pAssembly, QCall::ObjectHandleOnStack retPublicKey) | 
|---|
| 486 | { | 
|---|
| 487 | QCALL_CONTRACT; | 
|---|
| 488 |  | 
|---|
| 489 | BEGIN_QCALL; | 
|---|
| 490 |  | 
|---|
| 491 | DWORD cbPublicKey = 0; | 
|---|
| 492 | const void *pbPublicKey = pAssembly->GetFile()->GetPublicKey(&cbPublicKey); | 
|---|
| 493 | retPublicKey.SetByteArray((BYTE *)pbPublicKey, cbPublicKey); | 
|---|
| 494 |  | 
|---|
| 495 | END_QCALL; | 
|---|
| 496 | } | 
|---|
| 497 |  | 
|---|
| 498 | void QCALLTYPE AssemblyNative::GetSimpleName(QCall::AssemblyHandle pAssembly, QCall::StringHandleOnStack retSimpleName) | 
|---|
| 499 | { | 
|---|
| 500 | QCALL_CONTRACT; | 
|---|
| 501 |  | 
|---|
| 502 | BEGIN_QCALL; | 
|---|
| 503 | retSimpleName.Set(pAssembly->GetSimpleName()); | 
|---|
| 504 | END_QCALL; | 
|---|
| 505 | } | 
|---|
| 506 |  | 
|---|
| 507 | void QCALLTYPE AssemblyNative::GetLocale(QCall::AssemblyHandle pAssembly, QCall::StringHandleOnStack retString) | 
|---|
| 508 | { | 
|---|
| 509 | QCALL_CONTRACT; | 
|---|
| 510 |  | 
|---|
| 511 | BEGIN_QCALL; | 
|---|
| 512 |  | 
|---|
| 513 | LPCUTF8 pLocale = pAssembly->GetFile()->GetLocale(); | 
|---|
| 514 | if(pLocale) | 
|---|
| 515 | { | 
|---|
| 516 | retString.Set(pLocale); | 
|---|
| 517 | } | 
|---|
| 518 |  | 
|---|
| 519 | END_QCALL; | 
|---|
| 520 | } | 
|---|
| 521 |  | 
|---|
| 522 | void QCALLTYPE AssemblyNative::GetCodeBase(QCall::AssemblyHandle pAssembly, BOOL fCopiedName, QCall::StringHandleOnStack retString) | 
|---|
| 523 | { | 
|---|
| 524 | QCALL_CONTRACT; | 
|---|
| 525 |  | 
|---|
| 526 | BEGIN_QCALL; | 
|---|
| 527 |  | 
|---|
| 528 | StackSString codebase; | 
|---|
| 529 |  | 
|---|
| 530 | { | 
|---|
| 531 | pAssembly->GetFile()->GetCodeBase(codebase); | 
|---|
| 532 | } | 
|---|
| 533 |  | 
|---|
| 534 | retString.Set(codebase); | 
|---|
| 535 |  | 
|---|
| 536 | END_QCALL; | 
|---|
| 537 | } | 
|---|
| 538 |  | 
|---|
| 539 | INT32 QCALLTYPE AssemblyNative::GetHashAlgorithm(QCall::AssemblyHandle pAssembly) | 
|---|
| 540 | { | 
|---|
| 541 | QCALL_CONTRACT; | 
|---|
| 542 |  | 
|---|
| 543 | INT32 retVal=0; | 
|---|
| 544 | BEGIN_QCALL; | 
|---|
| 545 | retVal = pAssembly->GetFile()->GetHashAlgId(); | 
|---|
| 546 | END_QCALL; | 
|---|
| 547 | return retVal; | 
|---|
| 548 | } | 
|---|
| 549 |  | 
|---|
| 550 | INT32 QCALLTYPE AssemblyNative::GetFlags(QCall::AssemblyHandle pAssembly) | 
|---|
| 551 | { | 
|---|
| 552 | QCALL_CONTRACT; | 
|---|
| 553 |  | 
|---|
| 554 | INT32 retVal=0; | 
|---|
| 555 | BEGIN_QCALL; | 
|---|
| 556 | retVal = pAssembly->GetFile()->GetFlags(); | 
|---|
| 557 | END_QCALL; | 
|---|
| 558 | return retVal; | 
|---|
| 559 | } | 
|---|
| 560 |  | 
|---|
| 561 | BYTE * QCALLTYPE AssemblyNative::GetResource(QCall::AssemblyHandle pAssembly, LPCWSTR wszName, DWORD * length) | 
|---|
| 562 | { | 
|---|
| 563 | QCALL_CONTRACT; | 
|---|
| 564 |  | 
|---|
| 565 | PBYTE       pbInMemoryResource  = NULL; | 
|---|
| 566 |  | 
|---|
| 567 | BEGIN_QCALL; | 
|---|
| 568 |  | 
|---|
| 569 | if (wszName == NULL) | 
|---|
| 570 | COMPlusThrow(kArgumentNullException, W( "ArgumentNull_String")); | 
|---|
| 571 |  | 
|---|
| 572 | // Get the name in UTF8 | 
|---|
| 573 | SString name(SString::Literal, wszName); | 
|---|
| 574 |  | 
|---|
| 575 | StackScratchBuffer scratch; | 
|---|
| 576 | LPCUTF8 pNameUTF8 = name.GetUTF8(scratch); | 
|---|
| 577 |  | 
|---|
| 578 | if (*pNameUTF8 == '\0') | 
|---|
| 579 | COMPlusThrow(kArgumentException, W( "Format_StringZeroLength")); | 
|---|
| 580 |  | 
|---|
| 581 | pAssembly->GetResource(pNameUTF8, length, | 
|---|
| 582 | &pbInMemoryResource, NULL, NULL, | 
|---|
| 583 | NULL, FALSE); | 
|---|
| 584 |  | 
|---|
| 585 | END_QCALL; | 
|---|
| 586 |  | 
|---|
| 587 | // Can return null if resource file is zero-length | 
|---|
| 588 | return pbInMemoryResource; | 
|---|
| 589 | } | 
|---|
| 590 |  | 
|---|
| 591 | INT32 QCALLTYPE AssemblyNative::GetManifestResourceInfo(QCall::AssemblyHandle pAssembly, LPCWSTR wszName, QCall::ObjectHandleOnStack retAssembly, QCall::StringHandleOnStack retFileName) | 
|---|
| 592 | { | 
|---|
| 593 | QCALL_CONTRACT; | 
|---|
| 594 |  | 
|---|
| 595 | INT32 rv = -1; | 
|---|
| 596 |  | 
|---|
| 597 | BEGIN_QCALL; | 
|---|
| 598 |  | 
|---|
| 599 | if (wszName == NULL) | 
|---|
| 600 | COMPlusThrow(kArgumentNullException, W( "ArgumentNull_String")); | 
|---|
| 601 |  | 
|---|
| 602 | // Get the name in UTF8 | 
|---|
| 603 | SString name(SString::Literal, wszName); | 
|---|
| 604 |  | 
|---|
| 605 | StackScratchBuffer scratch; | 
|---|
| 606 | LPCUTF8 pNameUTF8 = name.GetUTF8(scratch); | 
|---|
| 607 |  | 
|---|
| 608 | if (*pNameUTF8 == '\0') | 
|---|
| 609 | COMPlusThrow(kArgumentException, W( "Format_StringZeroLength")); | 
|---|
| 610 |  | 
|---|
| 611 | DomainAssembly * pReferencedAssembly = NULL; | 
|---|
| 612 | LPCSTR pFileName = NULL; | 
|---|
| 613 | DWORD dwLocation = 0; | 
|---|
| 614 |  | 
|---|
| 615 | if (pAssembly->GetResource(pNameUTF8, NULL, NULL, &pReferencedAssembly, &pFileName, | 
|---|
| 616 | &dwLocation, FALSE)) | 
|---|
| 617 | { | 
|---|
| 618 | if (pFileName) | 
|---|
| 619 | retFileName.Set(pFileName); | 
|---|
| 620 |  | 
|---|
| 621 | GCX_COOP(); | 
|---|
| 622 |  | 
|---|
| 623 | if (pReferencedAssembly) | 
|---|
| 624 | retAssembly.Set(pReferencedAssembly->GetExposedAssemblyObject()); | 
|---|
| 625 |  | 
|---|
| 626 | rv = dwLocation; | 
|---|
| 627 | } | 
|---|
| 628 |  | 
|---|
| 629 | END_QCALL; | 
|---|
| 630 |  | 
|---|
| 631 | return rv; | 
|---|
| 632 | } | 
|---|
| 633 |  | 
|---|
| 634 | void QCALLTYPE AssemblyNative::GetModules(QCall::AssemblyHandle pAssembly, BOOL fLoadIfNotFound, BOOL fGetResourceModules, QCall::ObjectHandleOnStack retModules) | 
|---|
| 635 | { | 
|---|
| 636 | QCALL_CONTRACT; | 
|---|
| 637 |  | 
|---|
| 638 | BEGIN_QCALL; | 
|---|
| 639 |  | 
|---|
| 640 | HENUMInternalHolder phEnum(pAssembly->GetMDImport()); | 
|---|
| 641 | phEnum.EnumInit(mdtFile, mdTokenNil); | 
|---|
| 642 |  | 
|---|
| 643 | InlineSArray<DomainFile *, 8> modules; | 
|---|
| 644 |  | 
|---|
| 645 | modules.Append(pAssembly); | 
|---|
| 646 |  | 
|---|
| 647 | mdFile mdFile; | 
|---|
| 648 | while (pAssembly->GetMDImport()->EnumNext(&phEnum, &mdFile)) | 
|---|
| 649 | { | 
|---|
| 650 | DomainFile *pModule = pAssembly->GetModule()->LoadModule(GetAppDomain(), mdFile, fGetResourceModules, !fLoadIfNotFound); | 
|---|
| 651 |  | 
|---|
| 652 | if (pModule) { | 
|---|
| 653 | modules.Append(pModule); | 
|---|
| 654 | } | 
|---|
| 655 | } | 
|---|
| 656 |  | 
|---|
| 657 | { | 
|---|
| 658 | GCX_COOP(); | 
|---|
| 659 |  | 
|---|
| 660 | PTRARRAYREF orModules = NULL; | 
|---|
| 661 |  | 
|---|
| 662 | GCPROTECT_BEGIN(orModules); | 
|---|
| 663 |  | 
|---|
| 664 | // Return the modules | 
|---|
| 665 | orModules = (PTRARRAYREF)AllocateObjectArray(modules.GetCount(), MscorlibBinder::GetClass(CLASS__MODULE)); | 
|---|
| 666 |  | 
|---|
| 667 | for(COUNT_T i = 0; i < modules.GetCount(); i++) | 
|---|
| 668 | { | 
|---|
| 669 | DomainFile * pModule = modules[i]; | 
|---|
| 670 |  | 
|---|
| 671 | OBJECTREF o = pModule->GetExposedModuleObject(); | 
|---|
| 672 | orModules->SetAt(i, o); | 
|---|
| 673 | } | 
|---|
| 674 |  | 
|---|
| 675 | retModules.Set(orModules); | 
|---|
| 676 |  | 
|---|
| 677 | GCPROTECT_END(); | 
|---|
| 678 | } | 
|---|
| 679 |  | 
|---|
| 680 | END_QCALL; | 
|---|
| 681 | } | 
|---|
| 682 |  | 
|---|
| 683 | BOOL QCALLTYPE AssemblyNative::GetNeutralResourcesLanguageAttribute(QCall::AssemblyHandle pAssembly, QCall::StringHandleOnStack cultureName, INT16& outFallbackLocation) | 
|---|
| 684 | { | 
|---|
| 685 | CONTRACTL { | 
|---|
| 686 | QCALL_CHECK; | 
|---|
| 687 | } CONTRACTL_END; | 
|---|
| 688 |  | 
|---|
| 689 | BOOL retVal = FALSE; | 
|---|
| 690 | BEGIN_QCALL; | 
|---|
| 691 |  | 
|---|
| 692 | _ASSERTE(pAssembly); | 
|---|
| 693 | Assembly * pAsm = pAssembly->GetAssembly(); | 
|---|
| 694 | _ASSERTE(pAsm); | 
|---|
| 695 | Module * pModule = pAsm->GetManifestModule(); | 
|---|
| 696 | _ASSERTE(pModule); | 
|---|
| 697 |  | 
|---|
| 698 | LPCUTF8 pszCultureName = NULL; | 
|---|
| 699 | ULONG cultureNameLength = 0; | 
|---|
| 700 | INT16 fallbackLocation = 0; | 
|---|
| 701 |  | 
|---|
| 702 | // find the attribute if it exists | 
|---|
| 703 | if (pModule->GetNeutralResourcesLanguage(&pszCultureName, &cultureNameLength, &fallbackLocation, FALSE)) { | 
|---|
| 704 | StackSString culture(SString::Utf8, pszCultureName, cultureNameLength); | 
|---|
| 705 | cultureName.Set(culture); | 
|---|
| 706 | outFallbackLocation = fallbackLocation; | 
|---|
| 707 | retVal = TRUE; | 
|---|
| 708 | } | 
|---|
| 709 |  | 
|---|
| 710 | END_QCALL; | 
|---|
| 711 |  | 
|---|
| 712 | return retVal; | 
|---|
| 713 | } | 
|---|
| 714 |  | 
|---|
| 715 | BOOL QCALLTYPE AssemblyNative::GetIsCollectible(QCall::AssemblyHandle pAssembly) | 
|---|
| 716 | { | 
|---|
| 717 | QCALL_CONTRACT; | 
|---|
| 718 |  | 
|---|
| 719 | BOOL retVal = FALSE; | 
|---|
| 720 |  | 
|---|
| 721 | BEGIN_QCALL; | 
|---|
| 722 |  | 
|---|
| 723 | retVal = pAssembly->IsCollectible(); | 
|---|
| 724 |  | 
|---|
| 725 | END_QCALL; | 
|---|
| 726 |  | 
|---|
| 727 | return retVal; | 
|---|
| 728 | } | 
|---|
| 729 |  | 
|---|
| 730 | void QCALLTYPE AssemblyNative::GetModule(QCall::AssemblyHandle pAssembly, LPCWSTR wszFileName, QCall::ObjectHandleOnStack retModule) | 
|---|
| 731 | { | 
|---|
| 732 | QCALL_CONTRACT; | 
|---|
| 733 |  | 
|---|
| 734 | BEGIN_QCALL; | 
|---|
| 735 |  | 
|---|
| 736 | Module * pModule = NULL; | 
|---|
| 737 |  | 
|---|
| 738 | CQuickBytes qbLC; | 
|---|
| 739 |  | 
|---|
| 740 | if (wszFileName == NULL) | 
|---|
| 741 | COMPlusThrow(kArgumentNullException, W( "ArgumentNull_FileName")); | 
|---|
| 742 | if (wszFileName[0] == W('\0')) | 
|---|
| 743 | COMPlusThrow(kArgumentException, W( "Argument_EmptyFileName")); | 
|---|
| 744 |  | 
|---|
| 745 |  | 
|---|
| 746 | MAKE_UTF8PTR_FROMWIDE(szModuleName, wszFileName); | 
|---|
| 747 |  | 
|---|
| 748 |  | 
|---|
| 749 | LPCUTF8 pModuleName = NULL; | 
|---|
| 750 |  | 
|---|
| 751 | if SUCCEEDED(pAssembly->GetDomainAssembly()->GetModule()->GetScopeName(&pModuleName)) | 
|---|
| 752 | { | 
|---|
| 753 | if (::SString::_stricmp(pModuleName, szModuleName) == 0) | 
|---|
| 754 | pModule = pAssembly->GetDomainAssembly()->GetModule(); | 
|---|
| 755 | } | 
|---|
| 756 |  | 
|---|
| 757 |  | 
|---|
| 758 | if (pModule != NULL) | 
|---|
| 759 | { | 
|---|
| 760 | GCX_COOP(); | 
|---|
| 761 | retModule.Set(pModule->GetExposedObject()); | 
|---|
| 762 | } | 
|---|
| 763 |  | 
|---|
| 764 | END_QCALL; | 
|---|
| 765 |  | 
|---|
| 766 | return; | 
|---|
| 767 | } | 
|---|
| 768 |  | 
|---|
| 769 | void QCALLTYPE AssemblyNative::GetExportedTypes(QCall::AssemblyHandle pAssembly, QCall::ObjectHandleOnStack retTypes) | 
|---|
| 770 | { | 
|---|
| 771 | QCALL_CONTRACT; | 
|---|
| 772 |  | 
|---|
| 773 | BEGIN_QCALL; | 
|---|
| 774 |  | 
|---|
| 775 | InlineSArray<TypeHandle, 20> types; | 
|---|
| 776 |  | 
|---|
| 777 | Assembly * pAsm = pAssembly->GetAssembly(); | 
|---|
| 778 |  | 
|---|
| 779 | IMDInternalImport *pImport = pAsm->GetManifestImport(); | 
|---|
| 780 |  | 
|---|
| 781 | { | 
|---|
| 782 | HENUMTypeDefInternalHolder phTDEnum(pImport); | 
|---|
| 783 | phTDEnum.EnumTypeDefInit(); | 
|---|
| 784 |  | 
|---|
| 785 | mdTypeDef mdTD; | 
|---|
| 786 | while(pImport->EnumNext(&phTDEnum, &mdTD)) | 
|---|
| 787 | { | 
|---|
| 788 | DWORD dwFlags; | 
|---|
| 789 | IfFailThrow(pImport->GetTypeDefProps( | 
|---|
| 790 | mdTD, | 
|---|
| 791 | &dwFlags, | 
|---|
| 792 | NULL)); | 
|---|
| 793 |  | 
|---|
| 794 | // nested type | 
|---|
| 795 | mdTypeDef mdEncloser = mdTD; | 
|---|
| 796 | while (SUCCEEDED(pImport->GetNestedClassProps(mdEncloser, &mdEncloser)) && | 
|---|
| 797 | IsTdNestedPublic(dwFlags)) | 
|---|
| 798 | { | 
|---|
| 799 | IfFailThrow(pImport->GetTypeDefProps( | 
|---|
| 800 | mdEncloser, | 
|---|
| 801 | &dwFlags, | 
|---|
| 802 | NULL)); | 
|---|
| 803 | } | 
|---|
| 804 |  | 
|---|
| 805 | if (IsTdPublic(dwFlags)) | 
|---|
| 806 | { | 
|---|
| 807 | TypeHandle typeHnd = ClassLoader::LoadTypeDefThrowing(pAsm->GetManifestModule(), mdTD, | 
|---|
| 808 | ClassLoader::ThrowIfNotFound, | 
|---|
| 809 | ClassLoader::PermitUninstDefOrRef); | 
|---|
| 810 | types.Append(typeHnd); | 
|---|
| 811 | } | 
|---|
| 812 | } | 
|---|
| 813 | } | 
|---|
| 814 |  | 
|---|
| 815 | { | 
|---|
| 816 | HENUMInternalHolder phCTEnum(pImport); | 
|---|
| 817 | phCTEnum.EnumInit(mdtExportedType, mdTokenNil); | 
|---|
| 818 |  | 
|---|
| 819 | // Now get the ExportedTypes that don't have TD's in the manifest file | 
|---|
| 820 | mdExportedType mdCT; | 
|---|
| 821 | while(pImport->EnumNext(&phCTEnum, &mdCT)) | 
|---|
| 822 | { | 
|---|
| 823 | mdToken mdImpl; | 
|---|
| 824 | LPCSTR pszNameSpace; | 
|---|
| 825 | LPCSTR pszClassName; | 
|---|
| 826 | DWORD dwFlags; | 
|---|
| 827 |  | 
|---|
| 828 | IfFailThrow(pImport->GetExportedTypeProps( | 
|---|
| 829 | mdCT, | 
|---|
| 830 | &pszNameSpace, | 
|---|
| 831 | &pszClassName, | 
|---|
| 832 | &mdImpl, | 
|---|
| 833 | NULL,           //binding | 
|---|
| 834 | &dwFlags)); | 
|---|
| 835 |  | 
|---|
| 836 | // nested type | 
|---|
| 837 | while ((TypeFromToken(mdImpl) == mdtExportedType) && | 
|---|
| 838 | (mdImpl != mdExportedTypeNil) && | 
|---|
| 839 | IsTdNestedPublic(dwFlags)) | 
|---|
| 840 | { | 
|---|
| 841 | IfFailThrow(pImport->GetExportedTypeProps( | 
|---|
| 842 | mdImpl, | 
|---|
| 843 | NULL,       //namespace | 
|---|
| 844 | NULL,       //name | 
|---|
| 845 | &mdImpl, | 
|---|
| 846 | NULL,       //binding | 
|---|
| 847 | &dwFlags)); | 
|---|
| 848 | } | 
|---|
| 849 |  | 
|---|
| 850 | if ((TypeFromToken(mdImpl) == mdtFile) && | 
|---|
| 851 | (mdImpl != mdFileNil) && | 
|---|
| 852 | IsTdPublic(dwFlags)) | 
|---|
| 853 | { | 
|---|
| 854 | NameHandle typeName(pszNameSpace, pszClassName); | 
|---|
| 855 | typeName.SetTypeToken(pAsm->GetManifestModule(), mdCT); | 
|---|
| 856 | TypeHandle typeHnd = pAsm->GetLoader()->LoadTypeHandleThrowIfFailed(&typeName); | 
|---|
| 857 |  | 
|---|
| 858 | types.Append(typeHnd); | 
|---|
| 859 | } | 
|---|
| 860 | } | 
|---|
| 861 | } | 
|---|
| 862 |  | 
|---|
| 863 | { | 
|---|
| 864 | GCX_COOP(); | 
|---|
| 865 |  | 
|---|
| 866 | PTRARRAYREF orTypes = NULL; | 
|---|
| 867 |  | 
|---|
| 868 | GCPROTECT_BEGIN(orTypes); | 
|---|
| 869 |  | 
|---|
| 870 | // Return the types | 
|---|
| 871 | orTypes = (PTRARRAYREF)AllocateObjectArray(types.GetCount(), MscorlibBinder::GetClass(CLASS__TYPE)); | 
|---|
| 872 |  | 
|---|
| 873 | for(COUNT_T i = 0; i < types.GetCount(); i++) | 
|---|
| 874 | { | 
|---|
| 875 | TypeHandle typeHnd = types[i]; | 
|---|
| 876 |  | 
|---|
| 877 | OBJECTREF o = typeHnd.GetManagedClassObject(); | 
|---|
| 878 | orTypes->SetAt(i, o); | 
|---|
| 879 | } | 
|---|
| 880 |  | 
|---|
| 881 | retTypes.Set(orTypes); | 
|---|
| 882 |  | 
|---|
| 883 | GCPROTECT_END(); | 
|---|
| 884 | } | 
|---|
| 885 |  | 
|---|
| 886 | END_QCALL; | 
|---|
| 887 | } | 
|---|
| 888 |  | 
|---|
| 889 | void QCALLTYPE AssemblyNative::GetForwardedTypes(QCall::AssemblyHandle pAssembly, QCall::ObjectHandleOnStack retTypes) | 
|---|
| 890 | { | 
|---|
| 891 | QCALL_CONTRACT; | 
|---|
| 892 |  | 
|---|
| 893 | BEGIN_QCALL; | 
|---|
| 894 |  | 
|---|
| 895 | InlineSArray<TypeHandle, 8> types; | 
|---|
| 896 |  | 
|---|
| 897 | Assembly * pAsm = pAssembly->GetAssembly(); | 
|---|
| 898 |  | 
|---|
| 899 | IMDInternalImport *pImport = pAsm->GetManifestImport(); | 
|---|
| 900 |  | 
|---|
| 901 | // enumerate the ExportedTypes table | 
|---|
| 902 | { | 
|---|
| 903 | HENUMInternalHolder phCTEnum(pImport); | 
|---|
| 904 | phCTEnum.EnumInit(mdtExportedType, mdTokenNil); | 
|---|
| 905 |  | 
|---|
| 906 | // Now get the ExportedTypes that don't have TD's in the manifest file | 
|---|
| 907 | mdExportedType mdCT; | 
|---|
| 908 | while(pImport->EnumNext(&phCTEnum, &mdCT)) | 
|---|
| 909 | { | 
|---|
| 910 | mdToken mdImpl; | 
|---|
| 911 | LPCSTR pszNameSpace; | 
|---|
| 912 | LPCSTR pszClassName; | 
|---|
| 913 | DWORD dwFlags; | 
|---|
| 914 |  | 
|---|
| 915 | IfFailThrow(pImport->GetExportedTypeProps(mdCT, | 
|---|
| 916 | &pszNameSpace, | 
|---|
| 917 | &pszClassName, | 
|---|
| 918 | &mdImpl, | 
|---|
| 919 | NULL, //binding | 
|---|
| 920 | &dwFlags)); | 
|---|
| 921 |  | 
|---|
| 922 | if ((TypeFromToken(mdImpl) == mdtAssemblyRef) && (mdImpl != mdAssemblyRefNil)) | 
|---|
| 923 | { | 
|---|
| 924 | NameHandle typeName(pszNameSpace, pszClassName); | 
|---|
| 925 | typeName.SetTypeToken(pAsm->GetManifestModule(), mdCT); | 
|---|
| 926 | TypeHandle typeHnd = pAsm->GetLoader()->LoadTypeHandleThrowIfFailed(&typeName); | 
|---|
| 927 |  | 
|---|
| 928 | types.Append(typeHnd); | 
|---|
| 929 | } | 
|---|
| 930 | } | 
|---|
| 931 | } | 
|---|
| 932 |  | 
|---|
| 933 | // Populate retTypes | 
|---|
| 934 | { | 
|---|
| 935 | GCX_COOP(); | 
|---|
| 936 |  | 
|---|
| 937 | PTRARRAYREF orTypes = NULL; | 
|---|
| 938 |  | 
|---|
| 939 | GCPROTECT_BEGIN(orTypes); | 
|---|
| 940 |  | 
|---|
| 941 | // Return the types | 
|---|
| 942 | orTypes = (PTRARRAYREF)AllocateObjectArray(types.GetCount(), MscorlibBinder::GetClass(CLASS__TYPE)); | 
|---|
| 943 |  | 
|---|
| 944 | for(COUNT_T i = 0; i < types.GetCount(); i++) | 
|---|
| 945 | { | 
|---|
| 946 | TypeHandle typeHnd = types[i]; | 
|---|
| 947 |  | 
|---|
| 948 | OBJECTREF o = typeHnd.GetManagedClassObject(); | 
|---|
| 949 | orTypes->SetAt(i, o); | 
|---|
| 950 | } | 
|---|
| 951 |  | 
|---|
| 952 | retTypes.Set(orTypes); | 
|---|
| 953 |  | 
|---|
| 954 | GCPROTECT_END(); | 
|---|
| 955 | } | 
|---|
| 956 |  | 
|---|
| 957 | END_QCALL; | 
|---|
| 958 | } | 
|---|
| 959 |  | 
|---|
| 960 | FCIMPL1(Object*, AssemblyNative::GetManifestResourceNames, AssemblyBaseObject * pAssemblyUNSAFE) | 
|---|
| 961 | { | 
|---|
| 962 | FCALL_CONTRACT; | 
|---|
| 963 |  | 
|---|
| 964 | ASSEMBLYREF refAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pAssemblyUNSAFE); | 
|---|
| 965 |  | 
|---|
| 966 | if (refAssembly == NULL) | 
|---|
| 967 | FCThrowRes(kArgumentNullException, W( "Arg_InvalidHandle")); | 
|---|
| 968 |  | 
|---|
| 969 | DomainAssembly *pAssembly = refAssembly->GetDomainAssembly(); | 
|---|
| 970 | PTRARRAYREF rv = NULL; | 
|---|
| 971 |  | 
|---|
| 972 | HELPER_METHOD_FRAME_BEGIN_RET_2(rv, refAssembly); | 
|---|
| 973 |  | 
|---|
| 974 | IMDInternalImport *pImport = pAssembly->GetMDImport(); | 
|---|
| 975 |  | 
|---|
| 976 | HENUMInternalHolder phEnum(pImport); | 
|---|
| 977 | DWORD dwCount; | 
|---|
| 978 |  | 
|---|
| 979 | phEnum.EnumInit(mdtManifestResource, mdTokenNil); | 
|---|
| 980 | dwCount = pImport->EnumGetCount(&phEnum); | 
|---|
| 981 |  | 
|---|
| 982 | PTRARRAYREF ItemArray = (PTRARRAYREF) AllocateObjectArray(dwCount, g_pStringClass); | 
|---|
| 983 |  | 
|---|
| 984 | mdManifestResource mdResource; | 
|---|
| 985 |  | 
|---|
| 986 | GCPROTECT_BEGIN(ItemArray); | 
|---|
| 987 | for(DWORD i = 0;  i < dwCount; i++) { | 
|---|
| 988 | pImport->EnumNext(&phEnum, &mdResource); | 
|---|
| 989 | LPCSTR pszName = NULL; | 
|---|
| 990 |  | 
|---|
| 991 | IfFailThrow(pImport->GetManifestResourceProps( | 
|---|
| 992 | mdResource, | 
|---|
| 993 | &pszName,   // name | 
|---|
| 994 | NULL,       // linkref | 
|---|
| 995 | NULL,       // offset | 
|---|
| 996 | NULL));     //flags | 
|---|
| 997 |  | 
|---|
| 998 | OBJECTREF o = (OBJECTREF) StringObject::NewString(pszName); | 
|---|
| 999 | ItemArray->SetAt(i, o); | 
|---|
| 1000 | } | 
|---|
| 1001 |  | 
|---|
| 1002 | rv = ItemArray; | 
|---|
| 1003 | GCPROTECT_END(); | 
|---|
| 1004 |  | 
|---|
| 1005 | HELPER_METHOD_FRAME_END(); | 
|---|
| 1006 |  | 
|---|
| 1007 | return OBJECTREFToObject(rv); | 
|---|
| 1008 | } | 
|---|
| 1009 | FCIMPLEND | 
|---|
| 1010 |  | 
|---|
| 1011 | FCIMPL1(Object*, AssemblyNative::GetReferencedAssemblies, AssemblyBaseObject * pAssemblyUNSAFE) | 
|---|
| 1012 | { | 
|---|
| 1013 | FCALL_CONTRACT; | 
|---|
| 1014 |  | 
|---|
| 1015 | struct _gc { | 
|---|
| 1016 | PTRARRAYREF ItemArray; | 
|---|
| 1017 | ASSEMBLYNAMEREF pObj; | 
|---|
| 1018 | ASSEMBLYREF refAssembly; | 
|---|
| 1019 | } gc; | 
|---|
| 1020 | ZeroMemory(&gc, sizeof(gc)); | 
|---|
| 1021 |  | 
|---|
| 1022 | gc.refAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pAssemblyUNSAFE); | 
|---|
| 1023 |  | 
|---|
| 1024 | if (gc.refAssembly == NULL) | 
|---|
| 1025 | FCThrowRes(kArgumentNullException, W( "Arg_InvalidHandle")); | 
|---|
| 1026 |  | 
|---|
| 1027 | DomainAssembly *pAssembly = gc.refAssembly->GetDomainAssembly(); | 
|---|
| 1028 |  | 
|---|
| 1029 | HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); | 
|---|
| 1030 |  | 
|---|
| 1031 | IMDInternalImport *pImport = pAssembly->GetAssembly()->GetManifestImport(); | 
|---|
| 1032 |  | 
|---|
| 1033 | MethodTable* pAsmNameClass = MscorlibBinder::GetClass(CLASS__ASSEMBLY_NAME); | 
|---|
| 1034 |  | 
|---|
| 1035 | HENUMInternalHolder phEnum(pImport); | 
|---|
| 1036 | DWORD dwCount = 0; | 
|---|
| 1037 |  | 
|---|
| 1038 | phEnum.EnumInit(mdtAssemblyRef, mdTokenNil); | 
|---|
| 1039 |  | 
|---|
| 1040 | dwCount = pImport->EnumGetCount(&phEnum); | 
|---|
| 1041 |  | 
|---|
| 1042 | mdAssemblyRef mdAssemblyRef; | 
|---|
| 1043 |  | 
|---|
| 1044 | gc.ItemArray = (PTRARRAYREF) AllocateObjectArray(dwCount, pAsmNameClass); | 
|---|
| 1045 |  | 
|---|
| 1046 | for(DWORD i = 0; i < dwCount; i++) | 
|---|
| 1047 | { | 
|---|
| 1048 | pImport->EnumNext(&phEnum, &mdAssemblyRef); | 
|---|
| 1049 |  | 
|---|
| 1050 | AssemblySpec spec; | 
|---|
| 1051 | spec.InitializeSpec(mdAssemblyRef, pImport); | 
|---|
| 1052 |  | 
|---|
| 1053 | gc.pObj = (ASSEMBLYNAMEREF) AllocateObject(pAsmNameClass); | 
|---|
| 1054 | spec.AssemblyNameInit(&gc.pObj,NULL); | 
|---|
| 1055 |  | 
|---|
| 1056 | gc.ItemArray->SetAt(i, (OBJECTREF) gc.pObj); | 
|---|
| 1057 | } | 
|---|
| 1058 |  | 
|---|
| 1059 | HELPER_METHOD_FRAME_END(); | 
|---|
| 1060 |  | 
|---|
| 1061 | return OBJECTREFToObject(gc.ItemArray); | 
|---|
| 1062 | } | 
|---|
| 1063 | FCIMPLEND | 
|---|
| 1064 |  | 
|---|
| 1065 | void QCALLTYPE AssemblyNative::GetEntryPoint(QCall::AssemblyHandle pAssembly, QCall::ObjectHandleOnStack retMethod) | 
|---|
| 1066 | { | 
|---|
| 1067 | QCALL_CONTRACT; | 
|---|
| 1068 |  | 
|---|
| 1069 | MethodDesc* pMeth = NULL; | 
|---|
| 1070 |  | 
|---|
| 1071 | BEGIN_QCALL; | 
|---|
| 1072 |  | 
|---|
| 1073 | pMeth = pAssembly->GetAssembly()->GetEntryPoint(); | 
|---|
| 1074 | if (pMeth != NULL) | 
|---|
| 1075 | { | 
|---|
| 1076 | GCX_COOP(); | 
|---|
| 1077 | retMethod.Set(pMeth->GetStubMethodInfo()); | 
|---|
| 1078 | } | 
|---|
| 1079 |  | 
|---|
| 1080 | END_QCALL; | 
|---|
| 1081 |  | 
|---|
| 1082 | return; | 
|---|
| 1083 | } | 
|---|
| 1084 |  | 
|---|
| 1085 | //--------------------------------------------------------------------------------------- | 
|---|
| 1086 | // | 
|---|
| 1087 | // Release QCALL for System.SafePEFileHandle | 
|---|
| 1088 | // | 
|---|
| 1089 | // | 
|---|
| 1090 |  | 
|---|
| 1091 | void QCALLTYPE AssemblyNative::GetFullName(QCall::AssemblyHandle pAssembly, QCall::StringHandleOnStack retString) | 
|---|
| 1092 | { | 
|---|
| 1093 | QCALL_CONTRACT; | 
|---|
| 1094 |  | 
|---|
| 1095 | BEGIN_QCALL; | 
|---|
| 1096 |  | 
|---|
| 1097 | StackSString name; | 
|---|
| 1098 | pAssembly->GetFile()->GetDisplayName(name); | 
|---|
| 1099 | retString.Set(name); | 
|---|
| 1100 |  | 
|---|
| 1101 | END_QCALL; | 
|---|
| 1102 | } | 
|---|
| 1103 |  | 
|---|
| 1104 | void QCALLTYPE AssemblyNative::GetExecutingAssembly(QCall::StackCrawlMarkHandle stackMark, QCall::ObjectHandleOnStack retAssembly) | 
|---|
| 1105 | { | 
|---|
| 1106 | QCALL_CONTRACT; | 
|---|
| 1107 |  | 
|---|
| 1108 | DomainAssembly * pExecutingAssembly = NULL; | 
|---|
| 1109 |  | 
|---|
| 1110 | BEGIN_QCALL; | 
|---|
| 1111 |  | 
|---|
| 1112 | Assembly* pAssembly = SystemDomain::GetCallersAssembly(stackMark); | 
|---|
| 1113 | if(pAssembly) | 
|---|
| 1114 | { | 
|---|
| 1115 | pExecutingAssembly = pAssembly->GetDomainAssembly(); | 
|---|
| 1116 | GCX_COOP(); | 
|---|
| 1117 | retAssembly.Set(pExecutingAssembly->GetExposedAssemblyObject()); | 
|---|
| 1118 | } | 
|---|
| 1119 |  | 
|---|
| 1120 | END_QCALL; | 
|---|
| 1121 | return; | 
|---|
| 1122 | } | 
|---|
| 1123 |  | 
|---|
| 1124 | void QCALLTYPE AssemblyNative::GetEntryAssembly(QCall::ObjectHandleOnStack retAssembly) | 
|---|
| 1125 | { | 
|---|
| 1126 | QCALL_CONTRACT; | 
|---|
| 1127 |  | 
|---|
| 1128 | BEGIN_QCALL; | 
|---|
| 1129 |  | 
|---|
| 1130 | DomainAssembly * pRootAssembly = NULL; | 
|---|
| 1131 | Assembly * pAssembly = GetAppDomain()->m_pRootAssembly; | 
|---|
| 1132 |  | 
|---|
| 1133 | if (pAssembly) | 
|---|
| 1134 | { | 
|---|
| 1135 | pRootAssembly = pAssembly->GetDomainAssembly(); | 
|---|
| 1136 | GCX_COOP(); | 
|---|
| 1137 | retAssembly.Set(pRootAssembly->GetExposedAssemblyObject()); | 
|---|
| 1138 | } | 
|---|
| 1139 |  | 
|---|
| 1140 | END_QCALL; | 
|---|
| 1141 |  | 
|---|
| 1142 | return; | 
|---|
| 1143 | } | 
|---|
| 1144 |  | 
|---|
| 1145 | // return the in memory assembly module for reflection emit. This only works for dynamic assembly. | 
|---|
| 1146 | FCIMPL1(ReflectModuleBaseObject *, AssemblyNative::GetInMemoryAssemblyModule, AssemblyBaseObject* pAssemblyUNSAFE) | 
|---|
| 1147 | { | 
|---|
| 1148 | FCALL_CONTRACT; | 
|---|
| 1149 |  | 
|---|
| 1150 |  | 
|---|
| 1151 | ASSEMBLYREF refAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pAssemblyUNSAFE); | 
|---|
| 1152 |  | 
|---|
| 1153 | if (refAssembly == NULL) | 
|---|
| 1154 | FCThrowRes(kArgumentNullException, W( "Arg_InvalidHandle")); | 
|---|
| 1155 |  | 
|---|
| 1156 | DomainAssembly *pAssembly = refAssembly->GetDomainAssembly(); | 
|---|
| 1157 |  | 
|---|
| 1158 | FC_RETURN_MODULE_OBJECT(pAssembly->GetCurrentModule(), refAssembly); | 
|---|
| 1159 | } | 
|---|
| 1160 | FCIMPLEND | 
|---|
| 1161 |  | 
|---|
| 1162 | void QCALLTYPE AssemblyNative::GetImageRuntimeVersion(QCall::AssemblyHandle pAssembly, QCall::StringHandleOnStack retString) | 
|---|
| 1163 | { | 
|---|
| 1164 | QCALL_CONTRACT; | 
|---|
| 1165 |  | 
|---|
| 1166 | BEGIN_QCALL; | 
|---|
| 1167 |  | 
|---|
| 1168 | // Retrieve the PEFile from the assembly. | 
|---|
| 1169 | PEFile* pPEFile = pAssembly->GetFile(); | 
|---|
| 1170 | PREFIX_ASSUME(pPEFile!=NULL); | 
|---|
| 1171 |  | 
|---|
| 1172 | LPCSTR pszVersion = NULL; | 
|---|
| 1173 | IfFailThrow(pPEFile->GetMDImport()->GetVersionString(&pszVersion)); | 
|---|
| 1174 |  | 
|---|
| 1175 | SString version(SString::Utf8, pszVersion); | 
|---|
| 1176 |  | 
|---|
| 1177 | // Allocate a managed string that contains the version and return it. | 
|---|
| 1178 | retString.Set(version); | 
|---|
| 1179 |  | 
|---|
| 1180 | END_QCALL; | 
|---|
| 1181 | } | 
|---|
| 1182 |  | 
|---|
| 1183 | /*static*/ | 
|---|
| 1184 |  | 
|---|
| 1185 | INT_PTR QCALLTYPE AssemblyNative::InitializeAssemblyLoadContext(INT_PTR ptrManagedAssemblyLoadContext, BOOL fRepresentsTPALoadContext, BOOL fIsCollectible) | 
|---|
| 1186 | { | 
|---|
| 1187 | QCALL_CONTRACT; | 
|---|
| 1188 |  | 
|---|
| 1189 | INT_PTR ptrNativeAssemblyLoadContext = NULL; | 
|---|
| 1190 |  | 
|---|
| 1191 | BEGIN_QCALL; | 
|---|
| 1192 |  | 
|---|
| 1193 | // We do not need to take a lock since this method is invoked from the ctor of AssemblyLoadContext managed type and | 
|---|
| 1194 | // only one thread is ever executing a ctor for a given instance. | 
|---|
| 1195 | // | 
|---|
| 1196 |  | 
|---|
| 1197 | // Initialize the assembly binder instance in the VM | 
|---|
| 1198 | PTR_AppDomain pCurDomain = AppDomain::GetCurrentDomain(); | 
|---|
| 1199 | CLRPrivBinderCoreCLR *pTPABinderContext = pCurDomain->GetTPABinderContext(); | 
|---|
| 1200 | if (!fRepresentsTPALoadContext) | 
|---|
| 1201 | { | 
|---|
| 1202 | // Initialize a custom Assembly Load Context | 
|---|
| 1203 | CLRPrivBinderAssemblyLoadContext *pBindContext = NULL; | 
|---|
| 1204 |  | 
|---|
| 1205 | AssemblyLoaderAllocator* loaderAllocator = NULL; | 
|---|
| 1206 | OBJECTHANDLE loaderAllocatorHandle = NULL; | 
|---|
| 1207 |  | 
|---|
| 1208 | if (fIsCollectible) | 
|---|
| 1209 | { | 
|---|
| 1210 | // Create a new AssemblyLoaderAllocator for an AssemblyLoadContext | 
|---|
| 1211 | loaderAllocator = new AssemblyLoaderAllocator(); | 
|---|
| 1212 | loaderAllocator->SetCollectible(); | 
|---|
| 1213 |  | 
|---|
| 1214 | GCX_COOP(); | 
|---|
| 1215 | LOADERALLOCATORREF pManagedLoaderAllocator = NULL; | 
|---|
| 1216 | GCPROTECT_BEGIN(pManagedLoaderAllocator); | 
|---|
| 1217 | { | 
|---|
| 1218 | GCX_PREEMP(); | 
|---|
| 1219 | // Some of the initialization functions are not virtual. Call through the derived class | 
|---|
| 1220 | // to prevent calling the base class version. | 
|---|
| 1221 | loaderAllocator->Init(pCurDomain); | 
|---|
| 1222 | loaderAllocator->InitVirtualCallStubManager(pCurDomain); | 
|---|
| 1223 |  | 
|---|
| 1224 | // Setup the managed proxy now, but do not actually transfer ownership to it. | 
|---|
| 1225 | // Once everything is setup and nothing can fail anymore, the ownership will be | 
|---|
| 1226 | // atomically transfered by call to LoaderAllocator::ActivateManagedTracking(). | 
|---|
| 1227 | loaderAllocator->SetupManagedTracking(&pManagedLoaderAllocator); | 
|---|
| 1228 | } | 
|---|
| 1229 |  | 
|---|
| 1230 | // Create a strong handle to the LoaderAllocator | 
|---|
| 1231 | loaderAllocatorHandle = pCurDomain->CreateHandle(pManagedLoaderAllocator); | 
|---|
| 1232 |  | 
|---|
| 1233 | GCPROTECT_END(); | 
|---|
| 1234 |  | 
|---|
| 1235 | loaderAllocator->ActivateManagedTracking(); | 
|---|
| 1236 | } | 
|---|
| 1237 |  | 
|---|
| 1238 | IfFailThrow(CLRPrivBinderAssemblyLoadContext::SetupContext(pCurDomain->GetId().m_dwId, pTPABinderContext, loaderAllocator, loaderAllocatorHandle, ptrManagedAssemblyLoadContext, &pBindContext)); | 
|---|
| 1239 | ptrNativeAssemblyLoadContext = reinterpret_cast<INT_PTR>(pBindContext); | 
|---|
| 1240 | } | 
|---|
| 1241 | else | 
|---|
| 1242 | { | 
|---|
| 1243 | // We are initializing the managed instance of Assembly Load Context that would represent the TPA binder. | 
|---|
| 1244 | // First, confirm we do not have an existing managed ALC attached to the TPA binder. | 
|---|
| 1245 | INT_PTR ptrTPAAssemblyLoadContext = pTPABinderContext->GetManagedAssemblyLoadContext(); | 
|---|
| 1246 | if ((ptrTPAAssemblyLoadContext != NULL) && (ptrTPAAssemblyLoadContext != ptrManagedAssemblyLoadContext)) | 
|---|
| 1247 | { | 
|---|
| 1248 | COMPlusThrow(kInvalidOperationException, IDS_HOST_ASSEMBLY_RESOLVER_INCOMPATIBLE_TPA_BINDING_CONTEXT); | 
|---|
| 1249 | } | 
|---|
| 1250 |  | 
|---|
| 1251 | // Attach the managed TPA binding context with the native one. | 
|---|
| 1252 | pTPABinderContext->SetManagedAssemblyLoadContext(ptrManagedAssemblyLoadContext); | 
|---|
| 1253 | ptrNativeAssemblyLoadContext = reinterpret_cast<INT_PTR>(pTPABinderContext); | 
|---|
| 1254 | } | 
|---|
| 1255 |  | 
|---|
| 1256 | END_QCALL; | 
|---|
| 1257 |  | 
|---|
| 1258 | return ptrNativeAssemblyLoadContext; | 
|---|
| 1259 | } | 
|---|
| 1260 |  | 
|---|
| 1261 | /*static*/ | 
|---|
| 1262 | void QCALLTYPE AssemblyNative::PrepareForAssemblyLoadContextRelease(INT_PTR ptrNativeAssemblyLoadContext, INT_PTR ptrManagedStrongAssemblyLoadContext) | 
|---|
| 1263 | { | 
|---|
| 1264 | QCALL_CONTRACT; | 
|---|
| 1265 |  | 
|---|
| 1266 | BOOL fDestroyed = FALSE; | 
|---|
| 1267 |  | 
|---|
| 1268 | BEGIN_QCALL; | 
|---|
| 1269 |  | 
|---|
| 1270 |  | 
|---|
| 1271 | { | 
|---|
| 1272 | GCX_COOP(); | 
|---|
| 1273 | reinterpret_cast<CLRPrivBinderAssemblyLoadContext *>(ptrNativeAssemblyLoadContext)->PrepareForLoadContextRelease(ptrManagedStrongAssemblyLoadContext); | 
|---|
| 1274 | } | 
|---|
| 1275 |  | 
|---|
| 1276 | END_QCALL; | 
|---|
| 1277 | } | 
|---|
| 1278 |  | 
|---|
| 1279 | /*static*/ | 
|---|
| 1280 | INT_PTR QCALLTYPE AssemblyNative::GetLoadContextForAssembly(QCall::AssemblyHandle pAssembly) | 
|---|
| 1281 | { | 
|---|
| 1282 | QCALL_CONTRACT; | 
|---|
| 1283 |  | 
|---|
| 1284 | INT_PTR ptrManagedAssemblyLoadContext = NULL; | 
|---|
| 1285 |  | 
|---|
| 1286 | BEGIN_QCALL; | 
|---|
| 1287 |  | 
|---|
| 1288 | // Get the PEAssembly for the RuntimeAssembly | 
|---|
| 1289 | PEFile *pPEFile = pAssembly->GetFile(); | 
|---|
| 1290 | PTR_PEAssembly pPEAssembly = pPEFile->AsAssembly(); | 
|---|
| 1291 | _ASSERTE(pAssembly != NULL); | 
|---|
| 1292 |  | 
|---|
| 1293 | // Platform assemblies are semantically bound against the "Default" binder. | 
|---|
| 1294 | // The reference to the same will be returned when this QCall returns. | 
|---|
| 1295 |  | 
|---|
| 1296 | // Get the binding context for the assembly. | 
|---|
| 1297 | // | 
|---|
| 1298 | ICLRPrivBinder *pOpaqueBinder = nullptr; | 
|---|
| 1299 | AppDomain *pCurDomain = AppDomain::GetCurrentDomain(); | 
|---|
| 1300 | CLRPrivBinderCoreCLR *pTPABinder = pCurDomain->GetTPABinderContext(); | 
|---|
| 1301 |  | 
|---|
| 1302 | // GetBindingContext returns a ICLRPrivAssembly which can be used to get access to the | 
|---|
| 1303 | // actual ICLRPrivBinder instance in which the assembly was loaded. | 
|---|
| 1304 | PTR_ICLRPrivBinder pBindingContext = pPEAssembly->GetBindingContext(); | 
|---|
| 1305 | UINT_PTR assemblyBinderID = 0; | 
|---|
| 1306 | IfFailThrow(pBindingContext->GetBinderID(&assemblyBinderID)); | 
|---|
| 1307 |  | 
|---|
| 1308 | // If the assembly was bound using the TPA binder, | 
|---|
| 1309 | // then we will return the reference to "Default" binder from the managed implementation when this QCall returns. | 
|---|
| 1310 | // | 
|---|
| 1311 | // See earlier comment about "Default" binder for additional context. | 
|---|
| 1312 | pOpaqueBinder = reinterpret_cast<ICLRPrivBinder *>(assemblyBinderID); | 
|---|
| 1313 |  | 
|---|
| 1314 | // We should have a load context binder at this point. | 
|---|
| 1315 | _ASSERTE(pOpaqueBinder != nullptr); | 
|---|
| 1316 |  | 
|---|
| 1317 | if (!AreSameBinderInstance(pTPABinder, pOpaqueBinder)) | 
|---|
| 1318 | { | 
|---|
| 1319 | // Only CLRPrivBinderAssemblyLoadContext instance contains the reference to its | 
|---|
| 1320 | // corresponding managed instance. | 
|---|
| 1321 | CLRPrivBinderAssemblyLoadContext *pBinder = (CLRPrivBinderAssemblyLoadContext *)(pOpaqueBinder); | 
|---|
| 1322 |  | 
|---|
| 1323 | // Fetch the managed binder reference from the native binder instance | 
|---|
| 1324 | ptrManagedAssemblyLoadContext = pBinder->GetManagedAssemblyLoadContext(); | 
|---|
| 1325 | _ASSERTE(ptrManagedAssemblyLoadContext != NULL); | 
|---|
| 1326 | } | 
|---|
| 1327 |  | 
|---|
| 1328 | END_QCALL; | 
|---|
| 1329 |  | 
|---|
| 1330 | return ptrManagedAssemblyLoadContext; | 
|---|
| 1331 | } | 
|---|
| 1332 |  | 
|---|
| 1333 | // static | 
|---|
| 1334 | BOOL QCALLTYPE AssemblyNative::InternalTryGetRawMetadata( | 
|---|
| 1335 | QCall::AssemblyHandle assembly, | 
|---|
| 1336 | UINT8 **blobRef, | 
|---|
| 1337 | INT32 *lengthRef) | 
|---|
| 1338 | { | 
|---|
| 1339 | QCALL_CONTRACT; | 
|---|
| 1340 |  | 
|---|
| 1341 | PTR_CVOID metadata = nullptr; | 
|---|
| 1342 |  | 
|---|
| 1343 | BEGIN_QCALL; | 
|---|
| 1344 |  | 
|---|
| 1345 | _ASSERTE(assembly != nullptr); | 
|---|
| 1346 | _ASSERTE(blobRef != nullptr); | 
|---|
| 1347 | _ASSERTE(lengthRef != nullptr); | 
|---|
| 1348 |  | 
|---|
| 1349 | static_assert_no_msg(sizeof(*lengthRef) == sizeof(COUNT_T)); | 
|---|
| 1350 | metadata = assembly->GetFile()->GetLoadedMetadata(reinterpret_cast<COUNT_T *>(lengthRef)); | 
|---|
| 1351 | *blobRef = reinterpret_cast<UINT8 *>(const_cast<PTR_VOID>(metadata)); | 
|---|
| 1352 | _ASSERTE(*lengthRef >= 0); | 
|---|
| 1353 |  | 
|---|
| 1354 | END_QCALL; | 
|---|
| 1355 |  | 
|---|
| 1356 | return metadata != nullptr; | 
|---|
| 1357 | } | 
|---|
| 1358 |  | 
|---|