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.
8 #include "comdynamic.h"
9 #include "reflectclasswriter.h"
11 #include "ceesectionstring.h"
13 #include "typeparse.h"
15 #include "ildbsymlib.h"
18 //===============================================================================================
19 // CreateISymWriterforDynamicModule:
20 // Helper to create a ISymUnmanagedWriter instance and hook it up to a newly created dynamic
21 // module. This object is used to capture debugging information (source line info, etc.)
22 // for the dynamic module. This function determines the appropriate symbol format type
23 // (ILDB or PDB), and in the case of PDB (Windows desktop only) loads diasymreader.dll.
26 // mod - The ReflectionModule for the new dynamic module
27 // filenameTemp - the filename at which the module may be saved (ignored if no save access)
30 // The address where the new writer instance has been stored
31 //===============================================================================================
32 static ISymUnmanagedWriter **CreateISymWriterForDynamicModule(ReflectionModule *mod, const WCHAR *wszFilename)
36 _ASSERTE(mod->IsReflection());
38 // Determine which symbol format to use. For Silverlight 2.0 RTM we use ILDB mode to address security
39 // and portability issues with diasymreader.
41 // For desktop builds we'll eventually want to make ILDB is the default, but we need to emit PDB format if
42 // the symbols can be saved to disk to preserve back compat.
44 ESymbolFormat symFormatToUse = eSymbolFormatILDB;
47 static ConfigDWORD dbgForcePDBSymbols;
48 if(dbgForcePDBSymbols.val_DontUse_(W("DbgForcePDBSymbols"), 0) == 1)
50 symFormatToUse = eSymbolFormatPDB;
53 // Create a stream for the symbols to be emitted into. This
54 // lives on the Module for the life of the Module.
55 SafeComHolder<CGrowableStream> pStream(new CGrowableStream());
57 mod->SetInMemorySymbolStream(pStream, symFormatToUse);
59 // Create an ISymUnmanagedWriter and initialize it with the
60 // stream and the proper file name. This symbol writer will be
61 // replaced with new ones periodically as the symbols get
62 // retrieved by the debugger.
63 SafeComHolder<ISymUnmanagedWriter> pWriter;
66 if (symFormatToUse == eSymbolFormatILDB)
68 // Create an ILDB symbol writer from the ildbsymbols library statically linked in
69 hr = IldbSymbolsCreateInstance(CLSID_CorSymWriter_SxS,
70 IID_ISymUnmanagedWriter,
75 _ASSERTE(symFormatToUse == eSymbolFormatPDB);
76 hr = FakeCoCreateInstanceEx(CLSID_CorSymWriter_SxS,
77 GetInternalSystemDirectory(),
78 IID_ISymUnmanagedWriter,
88 // The other reference is given to the Sym Writer
89 // But, the writer takes it's own reference.
90 hr = pWriter->Initialize(mod->GetEmitter(),
97 mod->GetReflectionModule()->SetISymUnmanagedWriter(pWriter.Extract());
99 // Return the address of where we've got our
100 // ISymUnmanagedWriter stored so we can pass it over
101 // to the managed symbol writer object that most of
102 // reflection emit will use to write symbols.
103 return mod->GetISymUnmanagedWriterAddr();
116 //===============================================================================================
117 // Attaches an unmanaged symwriter to a newly created dynamic module.
118 //===============================================================================================
119 FCIMPL2(LPVOID, COMModule::nCreateISymWriterForDynamicModule, ReflectModuleBaseObject* reflectionModuleUNSAFE, StringObject* filenameUNSAFE)
123 REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(reflectionModuleUNSAFE);
125 ReflectionModule *mod = (ReflectionModule*)refModule->GetModule();
126 STRINGREF filename = (STRINGREF)filenameUNSAFE;
128 LPVOID pInternalSymWriter = NULL;
130 HELPER_METHOD_FRAME_BEGIN_RET_2(filename, refModule);
133 if (filename != NULL)
135 filename->GetSString(name);
139 pInternalSymWriter = CreateISymWriterForDynamicModule(mod, name.GetUnicode());
141 HELPER_METHOD_FRAME_END();
143 return pInternalSymWriter;
145 } // COMModule::nCreateISymWriterForDynamicModule
148 //**************************************************
149 // LoadInMemoryTypeByName
150 // Explicitly loading an in memory type
151 // <TODO>@todo: this function is not dealing with nested type correctly yet.
152 // We will need to parse the full name by finding "+" for enclosing type, etc.</TODO>
153 //**************************************************
154 void QCALLTYPE COMModule::LoadInMemoryTypeByName(QCall::ModuleHandle pModule, LPCWSTR wszFullName)
162 if (!pModule->IsReflection())
163 COMPlusThrow(kNotSupportedException, W("NotSupported_NonReflectedType"));
165 RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter();
168 // it is ok to use public import API because this is a dynamic module anyway. We are also receiving Unicode full name as
170 IMetaDataImport * pImport = pRCW->GetRWImporter();
172 if (wszFullName == NULL)
173 IfFailThrow( E_FAIL );
175 // look up the handle
177 HRESULT hr = pImport->FindTypeDefByName(wszFullName, mdTokenNil, &td);
180 if (hr != CLDB_E_RECORD_NOTFOUND)
183 // Get the UTF8 version of strFullName
184 MAKE_UTF8PTR_FROMWIDE(szFullName, wszFullName);
185 pModule->GetAssembly()->ThrowTypeLoadException(szFullName, IDS_CLASSLOAD_GENERAL);
188 TypeKey typeKey(pModule, td);
189 typeHnd = pModule->GetClassLoader()->LoadTypeHandleForTypeKey(&typeKey, TypeHandle());
196 //**************************************************
198 // This function will return the type token given full qual name. If the type
199 // is defined locally, we will return the TypeDef token. Or we will return a TypeRef token
200 // with proper resolution scope calculated.
201 // wszFullName is escaped (TYPE_NAME_RESERVED_CHAR). It should not be byref or contain enclosing type name,
202 // assembly name, and generic argument list.
203 //**************************************************
204 mdTypeRef QCALLTYPE COMModule::GetTypeRef(QCall::ModuleHandle pModule,
206 QCall::ModuleHandle pRefedModule,
207 LPCWSTR wszRefedModuleFileName,
208 INT32 tkResolutionArg)
216 RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter();
219 IMetaDataEmit * pEmit = pRCW->GetEmitter();
220 IMetaDataImport * pImport = pRCW->GetRWImporter();
222 if (wszFullName == NULL) {
223 COMPlusThrow(kArgumentNullException, W("ArgumentNull_String"));
226 InlineSString<128> ssNameUnescaped;
227 LPCWSTR wszTemp = wszFullName;
230 while(0 != (c = *wszTemp++))
233 IsTypeNameReservedChar(*wszTemp) )
235 ssNameUnescaped.Append(*wszTemp++);
239 _ASSERTE( ! IsTypeNameReservedChar(c) );
240 ssNameUnescaped.Append(c);
244 LPCWSTR wszFullNameUnescaped = ssNameUnescaped.GetUnicode();
246 Assembly * pThisAssembly = pModule->GetClassLoader()->GetAssembly();
247 Assembly * pRefedAssembly = pRefedModule->GetClassLoader()->GetAssembly();
249 if (pModule == pRefedModule)
251 // referenced type is from the same module so we must be able to find a TypeDef.
252 IfFailThrow(pImport->FindTypeDefByName(
253 wszFullNameUnescaped,
254 RidFromToken(tkResolutionArg) ? tkResolutionArg : mdTypeDefNil,
259 mdToken tkResolution = mdTokenNil;
260 if (RidFromToken(tkResolutionArg))
262 // reference to nested type
263 tkResolution = tkResolutionArg;
267 // reference to top level type
268 if ( pThisAssembly != pRefedAssembly )
270 SafeComHolderPreemp<IMetaDataAssemblyEmit> pAssemblyEmit;
272 // Generate AssemblyRef
273 IfFailThrow( pEmit->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) );
274 tkResolution = pThisAssembly->AddAssemblyRef(pRefedAssembly, pAssemblyEmit);
276 // Add the assembly ref token and the manifest module it is referring to this module's rid map.
277 // This is needed regardless of whether the dynamic assembly has run access. Even in Save-only
278 // or Refleciton-only mode, CreateType() of the referencing type may still need the referenced
279 // type to be resolved and loaded, e.g. if the referencing type is a subclass of the referenced type.
281 // Don't cache if there is assembly associated with the token already. The assembly ref resolution
282 // can be ambiguous because of reflection emit does not require unique assembly names.
283 // We always let the first association win. Ideally, we would disallow this situation by throwing
284 // exception, but that would be a breaking change.
285 if(pModule->LookupAssemblyRef(tkResolution) == NULL)
287 pModule->ForceStoreAssemblyRef(tkResolution, pRefedAssembly);
292 _ASSERTE(pModule != pRefedModule);
293 _ASSERTE(wszRefedModuleFileName != NULL);
295 // Generate ModuleRef
296 IfFailThrow(pEmit->DefineModuleRef(wszRefedModuleFileName, &tkResolution));
300 IfFailThrow( pEmit->DefineTypeRefByName(tkResolution, wszFullNameUnescaped, &tr) );
309 /*=============================GetArrayMethodToken==============================
312 **Arguments: REFLECTMODULEBASEREF refThis
314 ** STRINGREF methodName
317 ==============================================================================*/
318 INT32 QCALLTYPE COMModule::GetArrayMethodToken(QCall::ModuleHandle pModule,
320 LPCWSTR wszMethodName,
326 mdMemberRef memberRefE = mdTokenNil;
331 COMPlusThrow(kArgumentNullException, W("ArgumentNull_String"));
333 COMPlusThrow(kArgumentNullException, W("ArgumentNull_Type"));
335 RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter();
338 HRESULT hr = pRCW->GetEmitter()->DefineMemberRef(tkTypeSpec, wszMethodName, (PCCOR_SIGNATURE)pSignature, sigLength, &memberRefE);
341 _ASSERTE(!"Failed on DefineMemberRef");
347 return (INT32)memberRefE;
351 //******************************************************************************
354 // This function will return a MemberRef token given a MethodDef token and the module where the MethodDef/FieldDef is defined.
356 //******************************************************************************
357 INT32 QCALLTYPE COMModule::GetMemberRef(QCall::ModuleHandle pModule, QCall::ModuleHandle pRefedModule, INT32 tr, INT32 token)
361 mdMemberRef memberRefE = 0;
365 RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter();
370 PCCOR_SIGNATURE pvComSig;
372 if (TypeFromToken(token) == mdtMethodDef)
374 IfFailThrow(pRefedModule->GetMDImport()->GetNameOfMethodDef(token, &szName));
375 IfFailThrow(pRefedModule->GetMDImport()->GetSigOfMethodDef(token, &cbComSig, &pvComSig));
379 IfFailThrow(pRefedModule->GetMDImport()->GetNameOfFieldDef(token, &szName));
380 IfFailThrow(pRefedModule->GetMDImport()->GetSigOfFieldDef(token, &cbComSig, &pvComSig));
383 MAKE_WIDEPTR_FROMUTF8(wzName, szName);
385 // Translate the method sig into this scope
387 Assembly * pRefedAssembly = pRefedModule->GetAssembly();
388 Assembly * pRefingAssembly = pModule->GetAssembly();
390 if (pRefedAssembly->IsCollectible() && pRefedAssembly != pRefingAssembly)
392 if (pRefingAssembly->IsCollectible())
393 pRefingAssembly->GetLoaderAllocator()->EnsureReference(pRefedAssembly->GetLoaderAllocator());
395 COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleBoundNonCollectible"));
398 SafeComHolderPreemp<IMetaDataAssemblyEmit> pAssemblyEmit;
399 IfFailThrow( pRefingAssembly->GetManifestModule()->GetEmitter()->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) );
401 CQuickBytes qbNewSig;
404 IfFailThrow( pRefedModule->GetMDImport()->TranslateSigWithScope(
405 pRefedAssembly->GetManifestImport(),
406 NULL, 0, // hash value
409 pAssemblyEmit, // Emit assembly scope.
416 if (TypeFromToken(tr) == mdtTypeDef)
418 // define a TypeRef using the TypeDef
419 DefineTypeRefHelper(pRCW->GetEmitter(), tr, &tref);
424 // Define the memberRef
425 IfFailThrow( pRCW->GetEmitter()->DefineMemberRef(tref, wzName, (PCCOR_SIGNATURE) qbNewSig.Ptr(), cbNewSig, &memberRefE) );
429 // assign output parameter
430 return (INT32)memberRefE;
434 //******************************************************************************
436 // Return a TypeRef token given a TypeDef token from the same emit scope
438 //******************************************************************************
439 void COMModule::DefineTypeRefHelper(
440 IMetaDataEmit *pEmit, // given emit scope
441 mdTypeDef td, // given typedef in the emit scope
442 mdTypeRef *ptr) // return typeref
447 PRECONDITION(CheckPointer(pEmit));
448 PRECONDITION(CheckPointer(ptr));
453 WCHAR* szTypeDef = (WCHAR*) qb.AllocThrows((MAX_CLASSNAME_LENGTH+1) * sizeof(WCHAR));
454 mdToken rs; // resolution scope
457 SafeComHolder<IMetaDataImport> pImport;
458 IfFailThrow( pEmit->QueryInterface(IID_IMetaDataImport, (void **)&pImport) );
459 IfFailThrow( pImport->GetTypeDefProps(td, szTypeDef, MAX_CLASSNAME_LENGTH, NULL, &dwFlags, NULL) );
460 if ( IsTdNested(dwFlags) )
463 IfFailThrow( pImport->GetNestedClassProps(td, &tdNested) );
464 DefineTypeRefHelper( pEmit, tdNested, &rs);
467 rs = TokenFromRid( 1, mdtModule );
469 IfFailThrow( pEmit->DefineTypeRefByName( rs, szTypeDef, ptr) );
470 } // DefineTypeRefHelper
473 //******************************************************************************
475 // Return a MemberRef token given a RuntimeMethodInfo
477 //******************************************************************************
478 INT32 QCALLTYPE COMModule::GetMemberRefOfMethodInfo(QCall::ModuleHandle pModule, INT32 tr, MethodDesc * pMeth)
482 mdMemberRef memberRefE = 0;
487 COMPlusThrow(kArgumentNullException);
489 // Otherwise, we want to return memberref token.
490 if (pMeth->IsArray())
492 _ASSERTE(!"Should not have come here!");
493 COMPlusThrow(kNotSupportedException);
496 if (pMeth->GetMethodTable()->GetModule() == pModule)
498 // If the passed in method is defined in the same module, just return the MethodDef token
499 memberRefE = pMeth->GetMemberDef();
503 RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter();
507 IfFailThrow(pMeth->GetMDImport()->GetNameOfMethodDef(pMeth->GetMemberDef(), &szName));
510 PCCOR_SIGNATURE pvComSig;
511 IfFailThrow(pMeth->GetMDImport()->GetSigOfMethodDef(pMeth->GetMemberDef(), &cbComSig, &pvComSig));
513 // Translate the method sig into this scope
514 Assembly * pRefedAssembly = pMeth->GetModule()->GetAssembly();
515 Assembly * pRefingAssembly = pModule->GetAssembly();
517 SafeComHolderPreemp<IMetaDataAssemblyEmit> pAssemblyEmit;
518 IfFailThrow( pRefingAssembly->GetManifestModule()->GetEmitter()->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) );
520 CQuickBytes qbNewSig;
523 if (pRefedAssembly->IsCollectible() && pRefedAssembly != pRefingAssembly)
525 if (pRefingAssembly->IsCollectible())
526 pRefingAssembly->GetLoaderAllocator()->EnsureReference(pRefedAssembly->GetLoaderAllocator());
528 COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleBoundNonCollectible"));
531 IfFailThrow( pMeth->GetMDImport()->TranslateSigWithScope(
532 pRefedAssembly->GetManifestImport(),
533 NULL, 0, // hash blob value
536 pAssemblyEmit, // Emit assembly scope.
541 // translate the name to unicode string
542 MAKE_WIDEPTR_FROMUTF8(wszName, szName);
544 // Define the memberRef
545 IfFailThrow( pRCW->GetEmitter()->DefineMemberRef(tr, wszName, (PCCOR_SIGNATURE) qbNewSig.Ptr(), cbNewSig, &memberRefE) );
554 //******************************************************************************
556 // Return a MemberRef token given a RuntimeFieldInfo
558 //******************************************************************************
559 mdMemberRef QCALLTYPE COMModule::GetMemberRefOfFieldInfo(QCall::ModuleHandle pModule, mdTypeDef tr, QCall::TypeHandle th, mdFieldDef tkField)
563 mdMemberRef memberRefE = 0;
567 if (TypeFromToken(tr) == mdtTypeDef)
569 // If the passed in method is defined in the same module, just return the FieldDef token
570 memberRefE = tkField;
574 TypeHandle typeHandle = th.AsTypeHandle();
576 RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter();
579 // get the field name and sig
580 Module * pRefedModule = typeHandle.GetModule();
581 IMDInternalImport * pRefedMDImport = pRefedModule->GetMDImport();
584 IfFailThrow(pRefedMDImport->GetNameOfFieldDef(tkField, &szName));
587 PCCOR_SIGNATURE pvComSig;
588 IfFailThrow(pRefedMDImport->GetSigOfFieldDef(tkField, &cbComSig, &pvComSig));
590 // translate the name to unicode string
591 MAKE_WIDEPTR_FROMUTF8(wszName, szName);
593 Assembly * pRefedAssembly = pRefedModule->GetAssembly();
594 Assembly * pRefingAssembly = pModule->GetAssembly();
596 if (pRefedAssembly->IsCollectible() && pRefedAssembly != pRefingAssembly)
598 if (pRefingAssembly->IsCollectible())
599 pRefingAssembly->GetLoaderAllocator()->EnsureReference(pRefedAssembly->GetLoaderAllocator());
601 COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleBoundNonCollectible"));
603 SafeComHolderPreemp<IMetaDataAssemblyEmit> pAssemblyEmit;
604 IfFailThrow( pRefingAssembly->GetManifestModule()->GetEmitter()->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) );
606 // Translate the field signature this scope
607 CQuickBytes qbNewSig;
610 IfFailThrow( pRefedMDImport->TranslateSigWithScope(
611 pRefedAssembly->GetManifestImport(),
612 NULL, 0, // hash value
615 pAssemblyEmit, // Emit assembly scope.
620 IfFailThrow( pRCW->GetEmitter()->DefineMemberRef(tr, wszName, (PCCOR_SIGNATURE) qbNewSig.Ptr(), cbNewSig, &memberRefE) );
628 //******************************************************************************
630 // Return a MemberRef token given a Signature
632 //******************************************************************************
633 INT32 QCALLTYPE COMModule::GetMemberRefFromSignature(QCall::ModuleHandle pModule,
635 LPCWSTR wszMemberName,
641 mdMemberRef memberRefE = mdTokenNil;
645 RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter();
648 IfFailThrow( pRCW->GetEmitter()->DefineMemberRef(tr,
659 //******************************************************************************
661 // SetFieldRVAContent
662 // This function is used to set the FieldRVA with the content data
664 //******************************************************************************
665 void QCALLTYPE COMModule::SetFieldRVAContent(QCall::ModuleHandle pModule, INT32 tkField, LPCBYTE pContent, INT32 length)
671 RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter();
674 ICeeGen * pGen = pRCW->GetCeeGen();
676 ReflectionModule * pReflectionModule = pModule->GetReflectionModule();
678 // Create the .sdata section if not created
679 if (pReflectionModule->m_sdataSection == 0)
680 IfFailThrow( pGen->GetSectionCreate (".sdata", sdReadWrite, &pReflectionModule->m_sdataSection) );
682 // Get the size of current .sdata section. This will be the RVA for this field within the section
684 IfFailThrow( pGen->GetSectionDataLen(pReflectionModule->m_sdataSection, &dwRVA) );
685 dwRVA = (dwRVA + sizeof(DWORD)-1) & ~(sizeof(DWORD)-1);
687 // allocate the space in .sdata section
689 IfFailThrow( pGen->GetSectionBlock(pReflectionModule->m_sdataSection, length, sizeof(DWORD), (void**) &pvBlob) );
691 // copy over the initialized data if specified
692 if (pContent != NULL)
693 memcpy(pvBlob, pContent, length);
695 // set FieldRVA into metadata. Note that this is not final RVA in the image if save to disk. We will do another round of fix up upon save.
696 IfFailThrow( pRCW->GetEmitter()->SetFieldRVA(tkField, dwRVA) );
702 //******************************************************************************
705 // If this is a dynamic module, this routine will define a new
706 // string constant or return the token of an existing constant.
708 //******************************************************************************
709 mdString QCALLTYPE COMModule::GetStringConstant(QCall::ModuleHandle pModule, LPCWSTR pwzValue, INT32 iLength)
713 mdString strRef = mdTokenNil;
717 RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter();
720 _ASSERTE(pwzValue != NULL);
722 HRESULT hr = pRCW->GetEmitter()->DefineUserString(pwzValue, iLength, &strRef);
733 /*=============================SetModuleName====================================
735 ==============================================================================*/
736 void QCALLTYPE COMModule::SetModuleName(QCall::ModuleHandle pModule, LPCWSTR wszModuleName)
742 RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter();
745 IfFailThrow( pRCW->GetEmitter()->SetModuleProps(wszModuleName) );
750 //******************************************************************************
752 // Return a type spec token given a byte array
754 //******************************************************************************
755 BOOL QCALLTYPE COMModule::IsTransient(QCall::ModuleHandle pModule)
759 BOOL fIsTransient = FALSE;
763 /* Only reflection modules can be transient */
764 if (pModule->IsReflection())
765 fIsTransient = pModule->GetReflectionModule()->IsTransient();
772 //******************************************************************************
774 // Return a type spec token given a byte array
776 //******************************************************************************
777 mdTypeSpec QCALLTYPE COMModule::GetTokenFromTypeSpec(QCall::ModuleHandle pModule, LPCBYTE pSignature, INT32 sigLength)
781 mdTypeSpec ts = mdTokenNil;
785 RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter();
788 IfFailThrow(pRCW->GetEmitter()->GetTokenFromTypeSpec((PCCOR_SIGNATURE)pSignature, sigLength, &ts));
797 // Given a class name, this method will look for that class
798 // with in the module.
799 void QCALLTYPE COMModule::GetType(QCall::ModuleHandle pModule, LPCWSTR wszName, BOOL bThrowOnError, BOOL bIgnoreCase, QCall::ObjectHandleOnStack retType, QCall::ObjectHandleOnStack keepAlive)
804 PRECONDITION(CheckPointer(wszName));
808 TypeHandle retTypeHandle;
812 DomainAssembly *pAssembly = pModule->GetDomainAssembly();
815 BOOL prohibitAsmQualifiedName = TRUE;
817 // Load the class from this assembly (fail if it is in a different one).
818 retTypeHandle = TypeName::GetTypeManaged(wszName, pAssembly, bThrowOnError, bIgnoreCase, prohibitAsmQualifiedName, NULL, FALSE, (OBJECTREF*)keepAlive.m_ppObject);
820 // Verify that it's in 'this' module
821 // But, if it's in a different assembly than expected, that's okay, because
822 // it just means that it's been type forwarded.
823 if (!retTypeHandle.IsNull())
825 if ( (retTypeHandle.GetModule() != pModule) &&
826 (retTypeHandle.GetModule()->GetAssembly() == pModule->GetAssembly()) )
827 retTypeHandle = TypeHandle();
830 if (!retTypeHandle.IsNull())
833 retType.Set(retTypeHandle.GetManagedClassObject());
843 // This routine will return the name of the module as a String
844 void QCALLTYPE COMModule::GetScopeName(QCall::ModuleHandle pModule, QCall::StringHandleOnStack retString)
850 LPCSTR szName = NULL;
852 if (pModule->IsResource())
854 IfFailThrow(pModule->GetAssembly()->GetManifestImport()->GetFileProps(
855 pModule->GetModuleRef(),
863 if (!pModule->GetMDImport()->IsValidToken(pModule->GetMDImport()->GetModuleFromScope()))
865 ThrowHR(COR_E_BADIMAGEFORMAT);
867 IfFailThrow(pModule->GetMDImport()->GetScopeProps(&szName, 0));
870 retString.Set(szName);
875 static void ReplaceNiExtension(SString& fileName, PCWSTR pwzOldSuffix, PCWSTR pwzNewSuffix)
877 STANDARD_VM_CONTRACT;
879 if (fileName.EndsWithCaseInsensitive(pwzOldSuffix))
881 COUNT_T oldSuffixLen = (COUNT_T)wcslen(pwzOldSuffix);
882 fileName.Replace(fileName.End() - oldSuffixLen, oldSuffixLen, pwzNewSuffix);
886 /*============================GetFullyQualifiedName=============================
891 ==============================================================================*/
892 void QCALLTYPE COMModule::GetFullyQualifiedName(QCall::ModuleHandle pModule, QCall::StringHandleOnStack retString)
902 if (pModule->IsPEFile())
904 LPCWSTR fileName = pModule->GetPath();
905 if (*fileName != 0) {
906 retString.Set(fileName);
908 hr = UtilLoadStringRC(IDS_EE_NAME_UNKNOWN, wszBuffer, sizeof( wszBuffer ) / sizeof( WCHAR ), true );
911 retString.Set(wszBuffer);
916 hr = UtilLoadStringRC(IDS_EE_NAME_INMEMORYMODULE, wszBuffer, sizeof( wszBuffer ) / sizeof( WCHAR ), true );
919 retString.Set(wszBuffer);
925 /*===================================GetHINSTANCE===============================
926 **Action: Returns the hinst for this module.
930 ==============================================================================*/
931 HINSTANCE QCALLTYPE COMModule::GetHINSTANCE(QCall::ModuleHandle pModule)
935 HMODULE hMod = (HMODULE)0;
939 // This returns the base address - this will work for either HMODULE or HCORMODULES
940 // Other modules should have zero base
941 PEFile *pPEFile = pModule->GetFile();
942 if (!pPEFile->IsDynamic() && !pPEFile->IsResource())
944 hMod = (HMODULE) pModule->GetFile()->GetManagedFileContents();
947 //If we don't have an hMod, set it to -1 so that they know that there's none
955 return (HINSTANCE)hMod;
958 static Object* GetTypesInner(Module* pModule);
960 // Get class will return an array contain all of the classes
961 // that are defined within this Module.
962 FCIMPL1(Object*, COMModule::GetTypes, ReflectModuleBaseObject* pModuleUNSAFE)
966 OBJECTREF refRetVal = NULL;
967 REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
968 if (refModule == NULL)
969 FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
971 Module *pModule = refModule->GetModule();
973 HELPER_METHOD_FRAME_BEGIN_RET_2(refRetVal, refModule);
975 refRetVal = (OBJECTREF) GetTypesInner(pModule);
977 HELPER_METHOD_FRAME_END();
979 return OBJECTREFToObject(refRetVal);
983 Object* GetTypesInner(Module* pModule)
989 INJECT_FAULT(COMPlusThrowOM());
991 PRECONDITION(CheckPointer(pModule));
993 POSTCONDITION(CheckPointer(RETVAL));
997 DWORD dwNumTypeDefs = 0;
999 IMDInternalImport *pInternalImport;
1000 PTRARRAYREF refArrClasses = NULL;
1001 PTRARRAYREF xcept = NULL;
1003 HENUMInternal hEnum;
1004 bool bSystemAssembly; // Don't expose transparent proxy
1006 MethodTable* pMT = NULL;
1008 if (pModule->IsResource())
1010 refArrClasses = (PTRARRAYREF) AllocateObjectArray(0, MscorlibBinder::GetClass(CLASS__CLASS));
1011 RETURN(OBJECTREFToObject(refArrClasses));
1014 GCPROTECT_BEGIN(refArrClasses);
1015 GCPROTECT_BEGIN(xcept);
1017 pInternalImport = pModule->GetMDImport();
1019 HENUMTypeDefInternalHolder hEnum(pInternalImport);
1020 // Get the count of typedefs
1021 hEnum.EnumTypeDefInit();
1023 dwNumTypeDefs = pInternalImport->EnumTypeDefGetCount(&hEnum);
1025 // Allocate the COM+ array
1026 bSystemAssembly = (pModule->GetAssembly() == SystemDomain::SystemAssembly());
1027 AllocSize = dwNumTypeDefs;
1028 refArrClasses = (PTRARRAYREF) AllocateObjectArray(AllocSize, MscorlibBinder::GetClass(CLASS__CLASS));
1031 OBJECTREF throwable = 0;
1032 mdTypeDef tdCur = mdTypeDefNil;
1034 GCPROTECT_BEGIN(throwable);
1035 // Now create each COM+ Method object and insert it into the array.
1036 while (pInternalImport->EnumTypeDefNext(&hEnum, &tdCur))
1038 // Get the VM class for the current class token
1039 TypeHandle curClass;
1042 curClass = ClassLoader::LoadTypeDefOrRefThrowing(pModule, tdCur,
1043 ClassLoader::ThrowIfNotFound,
1044 ClassLoader::PermitUninstDefOrRef);
1046 EX_CATCH_THROWABLE(&throwable);
1048 if (throwable != 0) {
1049 // Lazily allocate an array to store the exceptions in
1051 xcept = (PTRARRAYREF) AllocateObjectArray(dwNumTypeDefs,g_pExceptionClass);
1053 _ASSERTE(cXcept < dwNumTypeDefs);
1054 xcept->SetAt(cXcept++, throwable);
1059 _ASSERTE("LoadClass failed." && !curClass.IsNull());
1061 pMT = curClass.GetMethodTable();
1062 PREFIX_ASSUME(pMT != NULL);
1064 // Get the COM+ Class object
1065 OBJECTREF refCurClass = pMT->GetManagedClassObject();
1066 _ASSERTE("GetManagedClassObject failed." && refCurClass != NULL);
1068 _ASSERTE(curPos < AllocSize);
1069 refArrClasses->SetAt(curPos++, refCurClass);
1071 GCPROTECT_END(); //throwable
1073 // check if there were exceptions thrown
1075 PTRARRAYREF xceptRet = NULL;
1076 GCPROTECT_BEGIN(xceptRet);
1078 xceptRet = (PTRARRAYREF) AllocateObjectArray(cXcept,g_pExceptionClass);
1079 for (i=0;i<cXcept;i++) {
1080 xceptRet->SetAt(i, xcept->GetAt(i));
1082 OBJECTREF except = InvokeUtil::CreateClassLoadExcept((OBJECTREF*) &refArrClasses,(OBJECTREF*) &xceptRet);
1083 COMPlusThrow(except);
1088 // We should have filled the array exactly.
1089 _ASSERTE(curPos == AllocSize);
1091 // Assign the return value to the COM+ array
1095 RETURN(OBJECTREFToObject(refArrClasses));
1099 FCIMPL1(FC_BOOL_RET, COMModule::IsResource, ReflectModuleBaseObject* pModuleUNSAFE)
1103 if (pModuleUNSAFE == NULL)
1104 FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1106 FC_RETURN_BOOL(pModuleUNSAFE->GetModule()->IsResource());
1111 //---------------------------------------------------------------------
1112 // Helper code for PunkSafeHandle class. This does the Release in the
1113 // safehandle's critical finalizer.
1114 //---------------------------------------------------------------------
1115 static VOID __stdcall DReleaseTarget(IUnknown *punk)
1132 //---------------------------------------------------------------------
1133 // Helper code for PunkSafeHandle class. This returns the function that performs
1134 // the Release() for the safehandle's critical finalizer.
1135 //---------------------------------------------------------------------
1136 FCIMPL0(void*, COMPunkSafeHandle::nGetDReleaseTarget)
1140 return (void*)DReleaseTarget;