//************************************************** // GetTypeRef // This function will return the type token given full qual name. If the type // is defined locally, we will return the TypeDef token. Or we will return a TypeRef token // with proper resolution scope calculated. // wszFullName is escaped (TYPE_NAME_RESERVED_CHAR). It should not be byref or contain enclosing type name, // assembly name, and generic argument list. //************************************************** mdTypeRef QCALLTYPE COMModule::GetTypeRef(QCall::ModuleHandle pModule, LPCWSTR wszFullName, QCall::ModuleHandle pRefedModule, LPCWSTR wszRefedModuleFileName, INT32 tkResolutionArg) { QCALL_CONTRACT; mdTypeRef tr = 0; BEGIN_QCALL; RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter(); _ASSERTE(pRCW); IMetaDataEmit * pEmit = pRCW->GetEmitter(); IMetaDataImport * pImport = pRCW->GetRWImporter(); if (wszFullName == NULL) { COMPlusThrow(kArgumentNullException, W("ArgumentNull_String")); } InlineSString<128> ssNameUnescaped; LPCWSTR wszTemp = wszFullName; WCHAR c; while(0 != (c = *wszTemp++)) { if ( c == W('\\') && IsTypeNameReservedChar(*wszTemp) ) { ssNameUnescaped.Append(*wszTemp++); } else { _ASSERTE( ! IsTypeNameReservedChar(c) ); ssNameUnescaped.Append(c); } } LPCWSTR wszFullNameUnescaped = ssNameUnescaped.GetUnicode(); Assembly * pThisAssembly = pModule->GetClassLoader()->GetAssembly(); Assembly * pRefedAssembly = pRefedModule->GetClassLoader()->GetAssembly(); if (pModule == pRefedModule) { // referenced type is from the same module so we must be able to find a TypeDef. IfFailThrow(pImport->FindTypeDefByName( wszFullNameUnescaped, RidFromToken(tkResolutionArg) ? tkResolutionArg : mdTypeDefNil, &tr)); } else { mdToken tkResolution = mdTokenNil; if (RidFromToken(tkResolutionArg)) { // reference to nested type tkResolution = tkResolutionArg; } else { // reference to top level type if ( pThisAssembly != pRefedAssembly ) { SafeComHolderPreemp<IMetaDataAssemblyEmit> pAssemblyEmit; // Generate AssemblyRef IfFailThrow( pEmit->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) ); tkResolution = pThisAssembly->AddAssemblyRef(pRefedAssembly, pAssemblyEmit); // Add the assembly ref token and the manifest module it is referring to this module's rid map. // This is needed regardless of whether the dynamic assembly has run access. Even in Save-only // or Refleciton-only mode, CreateType() of the referencing type may still need the referenced // type to be resolved and loaded, e.g. if the referencing type is a subclass of the referenced type. // // Don't cache if there is assembly associated with the token already. The assembly ref resolution // can be ambiguous because of reflection emit does not require unique assembly names. // We always let the first association win. Ideally, we would disallow this situation by throwing // exception, but that would be a breaking change. if(pModule->LookupAssemblyRef(tkResolution) == NULL) { pModule->ForceStoreAssemblyRef(tkResolution, pRefedAssembly); } } else { _ASSERTE(pModule != pRefedModule); _ASSERTE(wszRefedModuleFileName != NULL); // Generate ModuleRef IfFailThrow(pEmit->DefineModuleRef(wszRefedModuleFileName, &tkResolution)); } } IfFailThrow( pEmit->DefineTypeRefByName(tkResolution, wszFullNameUnescaped, &tr) ); } END_QCALL; return tr; }
LPSTR FillSymbolSearchPathThrows(CQuickBytes &qb) { STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_CANNOT_TAKE_LOCK; SCAN_IGNORE_FAULT; // Faults from Wsz funcs are handled. #ifndef DACCESS_COMPILE // not allowed to do allocation if current thread suspends EE. if (IsSuspendEEThread ()) return NULL; #endif InlineSString<MAX_SYM_PATH> rcBuff ; // Working buffer WCHAR rcVerString[64]; // Extension for install directory. int chTotal = 0; // How full is working buffer. int ch; // If the NT symbol server path vars are there, then use those. chTotal = WszGetEnvironmentVariable(W("_NT_SYMBOL_PATH"), rcBuff); if (chTotal + 1 < MAX_SYM_PATH) rcBuff.Append(W(';')); // Copy the defacto NT symbol path as well. size_t sympathLength = chTotal + NumItems(DEFAULT_SYM_PATH) + 1; // integer overflow occurred if (sympathLength < (size_t)chTotal || sympathLength < NumItems(DEFAULT_SYM_PATH)) { return NULL; } if (sympathLength < MAX_SYM_PATH) { rcBuff.Append(DEFAULT_SYM_PATH); chTotal = rcBuff.GetCount(); } // Next, if there is a URTTARGET, add that since that is where ndpsetup places // your symobls on an install. PathString rcBuffTemp; ch = WszGetEnvironmentVariable(W("URTTARGET"), rcBuffTemp); rcBuff.Append(rcBuffTemp); if (ch != 0 && (chTotal + ch + 1 < MAX_SYM_PATH)) { size_t chNewTotal = chTotal + ch; if (chNewTotal < (size_t)chTotal || chNewTotal < (size_t)ch) { // integer overflow occurred return NULL; } chTotal += ch; rcBuff.Append(W(';')); } #ifndef SELF_NO_HOST // Fetch the path location of the engine dll and add that path as well, just // in case URTARGET didn't cut it either. // For no-host builds of utilcode, we don't necessarily have an engine DLL in the // process, so skip this part. ch = WszGetModuleFileName(GetCLRModuleHack(), rcBuffTemp); size_t pathLocationLength = chTotal + ch + 1; // integer overflow occurred if (pathLocationLength < (size_t)chTotal || pathLocationLength < (size_t)ch) { return NULL; } if (ch != 0 && (pathLocationLength < MAX_SYM_PATH)) { chTotal = chTotal + ch - NumItems(STR_ENGINE_NAME); rcBuff.Append(W(';')); } #endif // Now we have a working buffer with a bunch of interesting stuff. Time // to convert it back to ansi for the imagehlp api's. Allocate the buffer // 2x bigger to handle worst case for MBCS. ch = ::WszWideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, rcBuff, -1, 0, 0, 0, 0); LPSTR szRtn = (LPSTR) qb.AllocNoThrow(ch + 1); if (!szRtn) return NULL; WszWideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, rcBuff, -1, szRtn, ch+1, 0, 0); return (szRtn); }