[Tizen] Unify dnetmemoryenumlib terms to match the codebase (#291)
[platform/upstream/coreclr.git] / src / vm / commodule.cpp
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 #include "common.h"
7 #include "commodule.h"
8 #include "comdynamic.h"
9 #include "reflectclasswriter.h"
10 #include "class.h"
11 #include "ceesectionstring.h"
12 #include <cor.h>
13 #include "typeparse.h"
14 #include "typekey.h"
15 #include "ildbsymlib.h"
16
17
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.
24 //
25 // Arguments:
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)
28 //   
29 // Return value:
30 //   The address where the new writer instance has been stored
31 //===============================================================================================
32 static ISymUnmanagedWriter **CreateISymWriterForDynamicModule(ReflectionModule *mod, const WCHAR *wszFilename)
33 {
34     STANDARD_VM_CONTRACT;
35     
36     _ASSERTE(mod->IsReflection());
37
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.
40     // 
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.
43     // 
44     ESymbolFormat symFormatToUse = eSymbolFormatILDB;
45
46    
47     static ConfigDWORD dbgForcePDBSymbols;
48     if(dbgForcePDBSymbols.val_DontUse_(W("DbgForcePDBSymbols"), 0) == 1)
49     {
50         symFormatToUse = eSymbolFormatPDB;
51     }
52
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());
56
57     mod->SetInMemorySymbolStream(pStream, symFormatToUse);
58
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;
64
65     HRESULT hr;
66     if (symFormatToUse == eSymbolFormatILDB)
67     {
68         // Create an ILDB symbol writer from the ildbsymbols library statically linked in
69         hr = IldbSymbolsCreateInstance(CLSID_CorSymWriter_SxS,
70                                           IID_ISymUnmanagedWriter,
71                                           (void**)&pWriter);
72     }
73     else
74     {
75         _ASSERTE(symFormatToUse == eSymbolFormatPDB);
76         hr = FakeCoCreateInstanceEx(CLSID_CorSymWriter_SxS,
77                                     GetInternalSystemDirectory(),
78                                     IID_ISymUnmanagedWriter,
79                                     (void**)&pWriter,
80                                     NULL);
81     }
82
83     if (SUCCEEDED(hr))
84     {
85         {
86             GCX_PREEMP();
87
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(),
91                                      wszFilename,
92                                      (IStream*)pStream,
93                                      TRUE);
94         }
95         if (SUCCEEDED(hr))
96         {
97             mod->GetReflectionModule()->SetISymUnmanagedWriter(pWriter.Extract());
98
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();
104         }
105         else
106         {
107             COMPlusThrowHR(hr);
108         }
109     }
110     else
111     {
112         COMPlusThrowHR(hr);
113     }
114 }
115
116 //===============================================================================================
117 // Attaches an unmanaged symwriter to a newly created dynamic module.
118 //===============================================================================================
119 FCIMPL2(LPVOID, COMModule::nCreateISymWriterForDynamicModule, ReflectModuleBaseObject* reflectionModuleUNSAFE, StringObject* filenameUNSAFE)
120 {
121     FCALL_CONTRACT;
122
123     REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(reflectionModuleUNSAFE);
124
125     ReflectionModule *mod = (ReflectionModule*)refModule->GetModule();
126     STRINGREF filename = (STRINGREF)filenameUNSAFE;
127
128     LPVOID pInternalSymWriter = NULL;
129     
130     HELPER_METHOD_FRAME_BEGIN_RET_2(filename, refModule);
131
132     SString name;
133     if (filename != NULL)
134     {
135         filename->GetSString(name);
136     }
137
138     GCX_PREEMP();
139     pInternalSymWriter = CreateISymWriterForDynamicModule(mod, name.GetUnicode());
140
141     HELPER_METHOD_FRAME_END();
142
143     return pInternalSymWriter;
144
145 } // COMModule::nCreateISymWriterForDynamicModule
146 FCIMPLEND
147
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)
155 {
156     QCALL_CONTRACT;
157     
158     TypeHandle      typeHnd;
159
160     BEGIN_QCALL;
161
162     if (!pModule->IsReflection())  
163         COMPlusThrow(kNotSupportedException, W("NotSupported_NonReflectedType"));   
164
165     RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter();
166     _ASSERTE(pRCW);
167
168     // it is ok to use public import API because this is a dynamic module anyway. We are also receiving Unicode full name as
169     // parameter.
170     IMetaDataImport * pImport = pRCW->GetRWImporter();
171
172     if (wszFullName == NULL)
173         IfFailThrow( E_FAIL );
174
175     // look up the handle
176     mdTypeDef  td;
177     HRESULT hr = pImport->FindTypeDefByName(wszFullName, mdTokenNil, &td);
178     if (FAILED(hr))
179     {
180         if (hr != CLDB_E_RECORD_NOTFOUND)
181             COMPlusThrowHR(hr);
182
183         // Get the UTF8 version of strFullName
184         MAKE_UTF8PTR_FROMWIDE(szFullName, wszFullName);
185         pModule->GetAssembly()->ThrowTypeLoadException(szFullName, IDS_CLASSLOAD_GENERAL);
186     }
187
188     TypeKey typeKey(pModule, td);
189     typeHnd = pModule->GetClassLoader()->LoadTypeHandleForTypeKey(&typeKey, TypeHandle());
190
191     END_QCALL;
192
193     return;
194 }
195
196 //**************************************************
197 // GetTypeRef
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,
205                                           LPCWSTR wszFullName,
206                                           QCall::ModuleHandle pRefedModule,
207                                           LPCWSTR wszRefedModuleFileName,
208                                           INT32 tkResolutionArg)
209 {
210     QCALL_CONTRACT;
211
212     mdTypeRef tr = 0;
213
214     BEGIN_QCALL;
215         
216     RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter();
217     _ASSERTE(pRCW); 
218     
219     IMetaDataEmit * pEmit = pRCW->GetEmitter(); 
220     IMetaDataImport * pImport = pRCW->GetRWImporter();
221
222     if (wszFullName == NULL) {
223         COMPlusThrow(kArgumentNullException, W("ArgumentNull_String"));
224     }    
225
226     InlineSString<128> ssNameUnescaped;
227     LPCWSTR wszTemp = wszFullName;
228
229     WCHAR c;
230     while(0 != (c = *wszTemp++))
231     {
232         if ( c == W('\\') && 
233              IsTypeNameReservedChar(*wszTemp) )
234         {
235             ssNameUnescaped.Append(*wszTemp++);
236         }
237         else
238         {
239             _ASSERTE( ! IsTypeNameReservedChar(c) );
240             ssNameUnescaped.Append(c);
241         }
242     }
243
244     LPCWSTR wszFullNameUnescaped = ssNameUnescaped.GetUnicode();
245
246     Assembly * pThisAssembly = pModule->GetClassLoader()->GetAssembly();
247     Assembly * pRefedAssembly = pRefedModule->GetClassLoader()->GetAssembly();
248
249     if (pModule == pRefedModule)
250     {
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,
255             &tr)); 
256     }
257     else
258     {
259         mdToken tkResolution = mdTokenNil;
260         if (RidFromToken(tkResolutionArg))
261         {
262             // reference to nested type
263             tkResolution = tkResolutionArg;
264         }
265         else
266         {
267             // reference to top level type
268             if ( pThisAssembly != pRefedAssembly )
269             {
270                 SafeComHolderPreemp<IMetaDataAssemblyEmit> pAssemblyEmit;  
271
272                 // Generate AssemblyRef
273                 IfFailThrow( pEmit->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) );
274                 tkResolution = pThisAssembly->AddAssemblyRef(pRefedAssembly, pAssemblyEmit);
275
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.
280                 //
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)
286                 {
287                     pModule->ForceStoreAssemblyRef(tkResolution, pRefedAssembly);
288                 }
289             }
290             else
291             {
292                 _ASSERTE(pModule != pRefedModule);                
293                 _ASSERTE(wszRefedModuleFileName != NULL);
294
295                 // Generate ModuleRef
296                 IfFailThrow(pEmit->DefineModuleRef(wszRefedModuleFileName, &tkResolution));
297             }
298         }
299
300         IfFailThrow( pEmit->DefineTypeRefByName(tkResolution, wszFullNameUnescaped, &tr) );  
301     }
302
303     END_QCALL;
304
305     return tr;
306 }
307
308
309 /*=============================GetArrayMethodToken==============================
310 **Action:
311 **Returns:
312 **Arguments: REFLECTMODULEBASEREF refThis
313 **           U1ARRAYREF     sig
314 **           STRINGREF      methodName
315 **           int            tkTypeSpec
316 **Exceptions:
317 ==============================================================================*/
318 INT32 QCALLTYPE COMModule::GetArrayMethodToken(QCall::ModuleHandle pModule,
319                                                INT32 tkTypeSpec,
320                                                LPCWSTR wszMethodName,
321                                                LPCBYTE pSignature,
322                                                INT32 sigLength)
323 {
324     QCALL_CONTRACT;
325
326     mdMemberRef memberRefE = mdTokenNil; 
327
328     BEGIN_QCALL;
329
330     if (!wszMethodName)
331         COMPlusThrow(kArgumentNullException, W("ArgumentNull_String"));
332     if (!tkTypeSpec) 
333         COMPlusThrow(kArgumentNullException, W("ArgumentNull_Type"));
334     
335     RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter(); 
336     _ASSERTE(pRCW); 
337
338     HRESULT hr = pRCW->GetEmitter()->DefineMemberRef(tkTypeSpec, wszMethodName, (PCCOR_SIGNATURE)pSignature, sigLength, &memberRefE); 
339     if (FAILED(hr)) 
340     {
341         _ASSERTE(!"Failed on DefineMemberRef");
342         COMPlusThrowHR(hr);
343     }
344
345     END_QCALL;
346
347     return (INT32)memberRefE;
348 }
349
350
351 //******************************************************************************
352 //
353 // GetMemberRefToken
354 // This function will return a MemberRef token given a MethodDef token and the module where the MethodDef/FieldDef is defined.
355 //
356 //******************************************************************************
357 INT32 QCALLTYPE COMModule::GetMemberRef(QCall::ModuleHandle pModule, QCall::ModuleHandle pRefedModule, INT32 tr, INT32 token)
358 {
359     QCALL_CONTRACT;
360     
361     mdMemberRef             memberRefE      = 0; 
362
363     BEGIN_QCALL;
364
365     RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter(); 
366     _ASSERTE( pRCW );
367     
368     LPCUTF8         szName;
369     ULONG           cbComSig;
370     PCCOR_SIGNATURE pvComSig;
371     
372     if (TypeFromToken(token) == mdtMethodDef)
373     {
374         IfFailThrow(pRefedModule->GetMDImport()->GetNameOfMethodDef(token, &szName));
375         IfFailThrow(pRefedModule->GetMDImport()->GetSigOfMethodDef(token, &cbComSig, &pvComSig));
376     }
377     else
378     {
379         IfFailThrow(pRefedModule->GetMDImport()->GetNameOfFieldDef(token, &szName));
380         IfFailThrow(pRefedModule->GetMDImport()->GetSigOfFieldDef(token, &cbComSig, &pvComSig));
381     }
382     
383     MAKE_WIDEPTR_FROMUTF8(wzName, szName);
384
385     // Translate the method sig into this scope 
386     //
387     Assembly * pRefedAssembly = pRefedModule->GetAssembly();
388     Assembly * pRefingAssembly = pModule->GetAssembly();
389
390     if (pRefedAssembly->IsCollectible() && pRefedAssembly != pRefingAssembly)
391     {
392         if (pRefingAssembly->IsCollectible())
393             pRefingAssembly->GetLoaderAllocator()->EnsureReference(pRefedAssembly->GetLoaderAllocator());
394         else
395             COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleBoundNonCollectible"));
396     }
397
398     SafeComHolderPreemp<IMetaDataAssemblyEmit> pAssemblyEmit;
399     IfFailThrow( pRefingAssembly->GetManifestModule()->GetEmitter()->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) );
400
401     CQuickBytes             qbNewSig; 
402     ULONG                   cbNewSig;      
403
404     IfFailThrow( pRefedModule->GetMDImport()->TranslateSigWithScope(
405         pRefedAssembly->GetManifestImport(), 
406         NULL, 0,        // hash value
407         pvComSig, 
408         cbComSig, 
409         pAssemblyEmit,  // Emit assembly scope.
410         pRCW->GetEmitter(), 
411         &qbNewSig, 
412         &cbNewSig) );  
413
414     mdTypeRef               tref;
415
416     if (TypeFromToken(tr) == mdtTypeDef)
417     {
418         // define a TypeRef using the TypeDef
419         DefineTypeRefHelper(pRCW->GetEmitter(), tr, &tref);
420     }
421     else 
422         tref = tr;
423
424     // Define the memberRef
425     IfFailThrow( pRCW->GetEmitter()->DefineMemberRef(tref, wzName, (PCCOR_SIGNATURE) qbNewSig.Ptr(), cbNewSig, &memberRefE) ); 
426
427     END_QCALL;
428
429     // assign output parameter
430     return (INT32)memberRefE;
431 }
432
433
434 //******************************************************************************
435 //
436 // Return a TypeRef token given a TypeDef token from the same emit scope
437 //
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
443 {
444     CONTRACTL  {
445         STANDARD_VM_CHECK;
446
447         PRECONDITION(CheckPointer(pEmit));
448         PRECONDITION(CheckPointer(ptr));
449     }
450     CONTRACTL_END;
451
452     CQuickBytes qb;
453     WCHAR* szTypeDef = (WCHAR*) qb.AllocThrows((MAX_CLASSNAME_LENGTH+1) * sizeof(WCHAR));
454     mdToken             rs;             // resolution scope
455     DWORD               dwFlags;
456
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) )
461     {
462         mdToken         tdNested;
463         IfFailThrow( pImport->GetNestedClassProps(td, &tdNested) );
464         DefineTypeRefHelper( pEmit, tdNested, &rs);
465     }
466     else
467         rs = TokenFromRid( 1, mdtModule );
468
469     IfFailThrow( pEmit->DefineTypeRefByName( rs, szTypeDef, ptr) );
470 }   // DefineTypeRefHelper
471
472
473 //******************************************************************************
474 //
475 // Return a MemberRef token given a RuntimeMethodInfo
476 //
477 //******************************************************************************
478 INT32 QCALLTYPE COMModule::GetMemberRefOfMethodInfo(QCall::ModuleHandle pModule, INT32 tr, MethodDesc * pMeth)
479 {
480     QCALL_CONTRACT;
481     
482     mdMemberRef memberRefE = 0; 
483     
484     BEGIN_QCALL;
485     
486     if (!pMeth)  
487         COMPlusThrow(kArgumentNullException);
488
489     // Otherwise, we want to return memberref token.
490     if (pMeth->IsArray())
491     {    
492         _ASSERTE(!"Should not have come here!");
493         COMPlusThrow(kNotSupportedException);    
494     }
495
496     if (pMeth->GetMethodTable()->GetModule() == pModule)
497     {
498         // If the passed in method is defined in the same module, just return the MethodDef token           
499         memberRefE = pMeth->GetMemberDef();
500     }
501     else
502     {
503         RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter(); 
504         _ASSERTE(pRCW); 
505         
506         LPCUTF8 szName;
507         IfFailThrow(pMeth->GetMDImport()->GetNameOfMethodDef(pMeth->GetMemberDef(), &szName));
508
509         ULONG           cbComSig;   
510         PCCOR_SIGNATURE pvComSig;
511         IfFailThrow(pMeth->GetMDImport()->GetSigOfMethodDef(pMeth->GetMemberDef(), &cbComSig, &pvComSig));
512
513         // Translate the method sig into this scope 
514         Assembly * pRefedAssembly = pMeth->GetModule()->GetAssembly();
515         Assembly * pRefingAssembly = pModule->GetAssembly();
516
517         SafeComHolderPreemp<IMetaDataAssemblyEmit> pAssemblyEmit;
518         IfFailThrow( pRefingAssembly->GetManifestModule()->GetEmitter()->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) );
519
520         CQuickBytes     qbNewSig;
521         ULONG           cbNewSig;
522
523         if (pRefedAssembly->IsCollectible() && pRefedAssembly != pRefingAssembly)
524         {
525             if (pRefingAssembly->IsCollectible())
526                 pRefingAssembly->GetLoaderAllocator()->EnsureReference(pRefedAssembly->GetLoaderAllocator());
527             else
528                 COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleBoundNonCollectible"));
529         }
530
531         IfFailThrow( pMeth->GetMDImport()->TranslateSigWithScope(
532             pRefedAssembly->GetManifestImport(), 
533             NULL, 0,        // hash blob value
534             pvComSig, 
535             cbComSig, 
536             pAssemblyEmit,  // Emit assembly scope.
537             pRCW->GetEmitter(), 
538             &qbNewSig, 
539             &cbNewSig) );  
540
541         // translate the name to unicode string
542         MAKE_WIDEPTR_FROMUTF8(wszName, szName);
543
544         // Define the memberRef
545         IfFailThrow( pRCW->GetEmitter()->DefineMemberRef(tr, wszName, (PCCOR_SIGNATURE) qbNewSig.Ptr(), cbNewSig, &memberRefE) );
546     }
547
548     END_QCALL;
549
550     return memberRefE;
551 }
552
553
554 //******************************************************************************
555 //
556 // Return a MemberRef token given a RuntimeFieldInfo
557 //
558 //******************************************************************************
559 mdMemberRef QCALLTYPE COMModule::GetMemberRefOfFieldInfo(QCall::ModuleHandle pModule, mdTypeDef tr, QCall::TypeHandle th, mdFieldDef tkField)
560 {
561     QCALL_CONTRACT;
562     
563     mdMemberRef memberRefE = 0;
564     
565     BEGIN_QCALL;
566     
567     if (TypeFromToken(tr) == mdtTypeDef)
568     {
569         // If the passed in method is defined in the same module, just return the FieldDef token           
570         memberRefE = tkField;
571     }
572     else
573     {
574         TypeHandle typeHandle = th.AsTypeHandle();
575
576         RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter(); 
577         _ASSERTE(pRCW);
578
579         // get the field name and sig
580         Module * pRefedModule = typeHandle.GetModule();
581         IMDInternalImport * pRefedMDImport = pRefedModule->GetMDImport();
582         
583         LPCUTF8 szName;
584         IfFailThrow(pRefedMDImport->GetNameOfFieldDef(tkField, &szName));
585
586         ULONG           cbComSig;   
587         PCCOR_SIGNATURE pvComSig;
588         IfFailThrow(pRefedMDImport->GetSigOfFieldDef(tkField, &cbComSig, &pvComSig));
589
590         // translate the name to unicode string
591         MAKE_WIDEPTR_FROMUTF8(wszName, szName);
592     
593         Assembly * pRefedAssembly = pRefedModule->GetAssembly();
594         Assembly * pRefingAssembly = pModule->GetAssembly();
595
596         if (pRefedAssembly->IsCollectible() && pRefedAssembly != pRefingAssembly)
597         {
598             if (pRefingAssembly->IsCollectible())
599                 pRefingAssembly->GetLoaderAllocator()->EnsureReference(pRefedAssembly->GetLoaderAllocator());
600             else
601                 COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleBoundNonCollectible"));
602         }
603         SafeComHolderPreemp<IMetaDataAssemblyEmit> pAssemblyEmit;
604         IfFailThrow( pRefingAssembly->GetManifestModule()->GetEmitter()->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) );
605
606         // Translate the field signature this scope  
607         CQuickBytes     qbNewSig;
608         ULONG           cbNewSig;   
609
610         IfFailThrow( pRefedMDImport->TranslateSigWithScope(
611         pRefedAssembly->GetManifestImport(), 
612         NULL, 0,            // hash value
613         pvComSig, 
614         cbComSig, 
615         pAssemblyEmit,      // Emit assembly scope.
616         pRCW->GetEmitter(), 
617         &qbNewSig, 
618         &cbNewSig) );  
619
620         IfFailThrow( pRCW->GetEmitter()->DefineMemberRef(tr, wszName, (PCCOR_SIGNATURE) qbNewSig.Ptr(), cbNewSig, &memberRefE) );
621     }
622
623     END_QCALL;
624
625     return memberRefE;  
626 }
627
628 //******************************************************************************
629 //
630 // Return a MemberRef token given a Signature
631 //
632 //******************************************************************************
633 INT32 QCALLTYPE COMModule::GetMemberRefFromSignature(QCall::ModuleHandle pModule, 
634                                                      INT32 tr,
635                                                      LPCWSTR wszMemberName,
636                                                      LPCBYTE pSignature,
637                                                      INT32 sigLength)
638 {
639     QCALL_CONTRACT;
640     
641     mdMemberRef     memberRefE = mdTokenNil; 
642
643     BEGIN_QCALL;
644
645     RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter(); 
646     _ASSERTE(pRCW);
647
648     IfFailThrow( pRCW->GetEmitter()->DefineMemberRef(tr, 
649                                                      wszMemberName, 
650                                                      pSignature, 
651                                                      sigLength, 
652                                                      &memberRefE) ); 
653
654     END_QCALL;
655
656     return memberRefE;  
657 }
658
659 //******************************************************************************
660 //
661 // SetFieldRVAContent
662 // This function is used to set the FieldRVA with the content data
663 //
664 //******************************************************************************
665 void QCALLTYPE COMModule::SetFieldRVAContent(QCall::ModuleHandle pModule, INT32 tkField, LPCBYTE pContent, INT32 length)
666 {
667     QCALL_CONTRACT;
668     
669     BEGIN_QCALL;
670
671     RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter(); 
672     _ASSERTE(pRCW); 
673
674     ICeeGen * pGen = pRCW->GetCeeGen();
675
676     ReflectionModule * pReflectionModule = pModule->GetReflectionModule();
677
678     // Create the .sdata section if not created
679     if (pReflectionModule->m_sdataSection == 0)
680         IfFailThrow( pGen->GetSectionCreate (".sdata", sdReadWrite, &pReflectionModule->m_sdataSection) );
681
682     // Get the size of current .sdata section. This will be the RVA for this field within the section
683     DWORD dwRVA = 0;
684     IfFailThrow( pGen->GetSectionDataLen(pReflectionModule->m_sdataSection, &dwRVA) );
685     dwRVA = (dwRVA + sizeof(DWORD)-1) & ~(sizeof(DWORD)-1);         
686
687     // allocate the space in .sdata section
688     void * pvBlob;
689     IfFailThrow( pGen->GetSectionBlock(pReflectionModule->m_sdataSection, length, sizeof(DWORD), (void**) &pvBlob) );
690
691     // copy over the initialized data if specified
692     if (pContent != NULL)
693         memcpy(pvBlob, pContent, length);
694
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) );
697
698     END_QCALL;  
699 }
700
701
702 //******************************************************************************
703 //
704 // GetStringConstant
705 // If this is a dynamic module, this routine will define a new 
706 //  string constant or return the token of an existing constant.    
707 //
708 //******************************************************************************
709 mdString QCALLTYPE COMModule::GetStringConstant(QCall::ModuleHandle pModule, LPCWSTR pwzValue, INT32 iLength)
710 {
711     QCALL_CONTRACT;
712     
713     mdString strRef = mdTokenNil;   
714
715     BEGIN_QCALL;
716
717     RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter();
718     _ASSERTE(pRCW); 
719     
720     _ASSERTE(pwzValue != NULL);
721
722     HRESULT hr = pRCW->GetEmitter()->DefineUserString(pwzValue, iLength, &strRef);
723     if (FAILED(hr)) { 
724         COMPlusThrowHR(hr);    
725     }   
726
727     END_QCALL;
728
729     return strRef;  
730 }
731
732
733 /*=============================SetModuleName====================================
734 // SetModuleName
735 ==============================================================================*/
736 void QCALLTYPE COMModule::SetModuleName(QCall::ModuleHandle pModule, LPCWSTR wszModuleName)
737 {
738     QCALL_CONTRACT;
739
740     BEGIN_QCALL;
741
742     RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter();
743     _ASSERTE(pRCW);
744
745     IfFailThrow( pRCW->GetEmitter()->SetModuleProps(wszModuleName) );
746
747     END_QCALL;
748 }
749
750 //******************************************************************************
751 //
752 // Return a type spec token given a byte array
753 //
754 //******************************************************************************
755 BOOL QCALLTYPE COMModule::IsTransient(QCall::ModuleHandle pModule)
756 {
757     QCALL_CONTRACT;
758
759     BOOL fIsTransient = FALSE;
760
761     BEGIN_QCALL;
762
763     /* Only reflection modules can be transient */
764     if (pModule->IsReflection())
765         fIsTransient = pModule->GetReflectionModule()->IsTransient();
766
767     END_QCALL;
768
769     return fIsTransient;
770 }
771
772 //******************************************************************************
773 //
774 // Return a type spec token given a byte array
775 //
776 //******************************************************************************
777 mdTypeSpec QCALLTYPE COMModule::GetTokenFromTypeSpec(QCall::ModuleHandle pModule, LPCBYTE pSignature, INT32 sigLength)
778 {
779     QCALL_CONTRACT;
780     
781     mdTypeSpec      ts = mdTokenNil;
782
783     BEGIN_QCALL;
784
785     RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter(); 
786     _ASSERTE(pRCW); 
787
788     IfFailThrow(pRCW->GetEmitter()->GetTokenFromTypeSpec((PCCOR_SIGNATURE)pSignature, sigLength, &ts));
789
790     END_QCALL;
791
792     return ts;
793 }
794
795
796 // GetType
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)
800 {
801     CONTRACTL
802     {
803         QCALL_CHECK;
804         PRECONDITION(CheckPointer(wszName));
805     }
806     CONTRACTL_END;
807     
808     TypeHandle retTypeHandle;
809
810     BEGIN_QCALL;
811
812     DomainAssembly *pAssembly = pModule->GetDomainAssembly();
813     _ASSERTE(pAssembly);
814
815     BOOL prohibitAsmQualifiedName = TRUE;
816
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);
819
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())
824     {
825         if ( (retTypeHandle.GetModule() != pModule) &&
826              (retTypeHandle.GetModule()->GetAssembly() == pModule->GetAssembly()) )
827             retTypeHandle = TypeHandle();
828     }
829
830     if (!retTypeHandle.IsNull())
831     {
832         GCX_COOP();
833         retType.Set(retTypeHandle.GetManagedClassObject());
834     }
835  
836     END_QCALL;
837
838     return;
839 }
840
841
842 // GetName
843 // This routine will return the name of the module as a String
844 void QCALLTYPE COMModule::GetScopeName(QCall::ModuleHandle pModule, QCall::StringHandleOnStack retString)
845 {
846     QCALL_CONTRACT;
847     
848     BEGIN_QCALL;
849     
850     LPCSTR    szName = NULL;
851     
852     if (pModule->IsResource())
853     {
854         IfFailThrow(pModule->GetAssembly()->GetManifestImport()->GetFileProps(
855             pModule->GetModuleRef(), 
856             &szName, 
857             NULL, 
858             NULL, 
859             NULL));
860     }
861     else
862     {
863         if (!pModule->GetMDImport()->IsValidToken(pModule->GetMDImport()->GetModuleFromScope()))
864         {
865             ThrowHR(COR_E_BADIMAGEFORMAT);
866         }
867         IfFailThrow(pModule->GetMDImport()->GetScopeProps(&szName, 0));
868     }
869     
870     retString.Set(szName);
871     
872     END_QCALL;
873 }
874
875 static void ReplaceNiExtension(SString& fileName, PCWSTR pwzOldSuffix, PCWSTR pwzNewSuffix)
876 {
877     STANDARD_VM_CONTRACT;
878
879     if (fileName.EndsWithCaseInsensitive(pwzOldSuffix))
880     {
881         COUNT_T oldSuffixLen = (COUNT_T)wcslen(pwzOldSuffix);
882         fileName.Replace(fileName.End() - oldSuffixLen, oldSuffixLen, pwzNewSuffix);
883     }
884 }
885
886 /*============================GetFullyQualifiedName=============================
887 **Action:
888 **Returns:
889 **Arguments:
890 **Exceptions:
891 ==============================================================================*/
892 void QCALLTYPE COMModule::GetFullyQualifiedName(QCall::ModuleHandle pModule, QCall::StringHandleOnStack retString)
893 {
894     QCALL_CONTRACT;
895
896     BEGIN_QCALL;
897     
898     HRESULT hr = S_OK;
899
900     WCHAR wszBuffer[64];
901
902     if (pModule->IsPEFile())
903     {
904         LPCWSTR fileName = pModule->GetPath();
905         if (*fileName != 0) {
906                 retString.Set(fileName);
907         } else {
908             hr = UtilLoadStringRC(IDS_EE_NAME_UNKNOWN, wszBuffer, sizeof( wszBuffer ) / sizeof( WCHAR ), true );
909             if (FAILED(hr))
910                 COMPlusThrowHR(hr);
911             retString.Set(wszBuffer);               
912         }
913     }
914     else
915     {
916         hr = UtilLoadStringRC(IDS_EE_NAME_INMEMORYMODULE, wszBuffer, sizeof( wszBuffer ) / sizeof( WCHAR ), true );
917         if (FAILED(hr))
918             COMPlusThrowHR(hr);
919         retString.Set(wszBuffer);            
920     }
921
922     END_QCALL;
923 }
924
925 /*===================================GetHINSTANCE===============================
926 **Action:  Returns the hinst for this module.
927 **Returns:
928 **Arguments: refThis
929 **Exceptions: None.
930 ==============================================================================*/
931 HINSTANCE QCALLTYPE COMModule::GetHINSTANCE(QCall::ModuleHandle pModule)
932 {
933     QCALL_CONTRACT;
934     
935     HMODULE hMod = (HMODULE)0;
936     
937     BEGIN_QCALL;
938
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())
943     {
944         hMod = (HMODULE) pModule->GetFile()->GetManagedFileContents();
945     }
946
947     //If we don't have an hMod, set it to -1 so that they know that there's none
948     //available
949     if (!hMod) {
950         hMod = (HMODULE)-1;
951     }
952
953     END_QCALL;
954
955     return (HINSTANCE)hMod;
956 }
957
958 static Object* GetTypesInner(Module* pModule);
959
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)
963 {
964     FCALL_CONTRACT;
965
966     OBJECTREF   refRetVal   = NULL;
967     REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
968     if (refModule == NULL)
969         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
970
971     Module *pModule = refModule->GetModule();
972
973     HELPER_METHOD_FRAME_BEGIN_RET_2(refRetVal, refModule);
974
975     refRetVal = (OBJECTREF) GetTypesInner(pModule);
976
977     HELPER_METHOD_FRAME_END();
978
979     return OBJECTREFToObject(refRetVal);
980 }
981 FCIMPLEND
982
983 Object* GetTypesInner(Module* pModule)
984 {
985     CONTRACT(Object*) {
986         THROWS;
987         GC_TRIGGERS;
988         MODE_COOPERATIVE; 
989         INJECT_FAULT(COMPlusThrowOM());
990
991         PRECONDITION(CheckPointer(pModule));
992
993         POSTCONDITION(CheckPointer(RETVAL));
994     }
995     CONTRACT_END;
996
997     DWORD           dwNumTypeDefs = 0;
998     DWORD           i;
999     IMDInternalImport *pInternalImport;
1000     PTRARRAYREF     refArrClasses = NULL;
1001     PTRARRAYREF     xcept = NULL;
1002     DWORD           cXcept = 0;
1003     HENUMInternal   hEnum;
1004     bool            bSystemAssembly;    // Don't expose transparent proxy
1005     int             AllocSize = 0;
1006     MethodTable* pMT = NULL;
1007
1008     if (pModule->IsResource())
1009     {
1010         refArrClasses = (PTRARRAYREF) AllocateObjectArray(0, MscorlibBinder::GetClass(CLASS__CLASS));
1011         RETURN(OBJECTREFToObject(refArrClasses));
1012     }
1013
1014     GCPROTECT_BEGIN(refArrClasses);
1015     GCPROTECT_BEGIN(xcept);
1016
1017     pInternalImport = pModule->GetMDImport();
1018
1019     HENUMTypeDefInternalHolder hEnum(pInternalImport);
1020     // Get the count of typedefs
1021     hEnum.EnumTypeDefInit();
1022
1023     dwNumTypeDefs = pInternalImport->EnumTypeDefGetCount(&hEnum);
1024
1025     // Allocate the COM+ array
1026     bSystemAssembly = (pModule->GetAssembly() == SystemDomain::SystemAssembly());
1027     AllocSize = dwNumTypeDefs;
1028     refArrClasses = (PTRARRAYREF) AllocateObjectArray(AllocSize, MscorlibBinder::GetClass(CLASS__CLASS));
1029
1030     int curPos = 0;
1031     OBJECTREF throwable = 0;
1032     mdTypeDef tdCur = mdTypeDefNil;
1033
1034     GCPROTECT_BEGIN(throwable);
1035     // Now create each COM+ Method object and insert it into the array.
1036     while (pInternalImport->EnumTypeDefNext(&hEnum, &tdCur))
1037     {
1038         // Get the VM class for the current class token
1039         TypeHandle curClass;
1040
1041         EX_TRY {
1042             curClass = ClassLoader::LoadTypeDefOrRefThrowing(pModule, tdCur,
1043                                              ClassLoader::ThrowIfNotFound, 
1044                                              ClassLoader::PermitUninstDefOrRef);
1045         }
1046         EX_CATCH_THROWABLE(&throwable);
1047
1048         if (throwable != 0) {
1049             // Lazily allocate an array to store the exceptions in
1050             if (xcept == NULL)
1051                 xcept = (PTRARRAYREF) AllocateObjectArray(dwNumTypeDefs,g_pExceptionClass);
1052
1053             _ASSERTE(cXcept < dwNumTypeDefs);
1054             xcept->SetAt(cXcept++, throwable);
1055             throwable = 0;
1056             continue;
1057         }
1058
1059         _ASSERTE("LoadClass failed." && !curClass.IsNull());
1060
1061         pMT = curClass.GetMethodTable();
1062         PREFIX_ASSUME(pMT != NULL);
1063
1064         // Get the COM+ Class object
1065         OBJECTREF refCurClass = pMT->GetManagedClassObject();
1066         _ASSERTE("GetManagedClassObject failed." && refCurClass != NULL);
1067
1068         _ASSERTE(curPos < AllocSize);
1069         refArrClasses->SetAt(curPos++, refCurClass);
1070     }
1071     GCPROTECT_END();    //throwable
1072
1073     // check if there were exceptions thrown
1074     if (cXcept > 0) {
1075         PTRARRAYREF xceptRet = NULL;
1076         GCPROTECT_BEGIN(xceptRet);
1077         
1078         xceptRet = (PTRARRAYREF) AllocateObjectArray(cXcept,g_pExceptionClass);
1079         for (i=0;i<cXcept;i++) {
1080             xceptRet->SetAt(i, xcept->GetAt(i));
1081         }
1082         OBJECTREF except = InvokeUtil::CreateClassLoadExcept((OBJECTREF*) &refArrClasses,(OBJECTREF*) &xceptRet);
1083         COMPlusThrow(except);
1084         
1085         GCPROTECT_END();
1086     }
1087
1088     // We should have filled the array exactly.
1089     _ASSERTE(curPos == AllocSize);
1090
1091     // Assign the return value to the COM+ array
1092     GCPROTECT_END();
1093     GCPROTECT_END();
1094
1095     RETURN(OBJECTREFToObject(refArrClasses));
1096 }
1097
1098
1099 FCIMPL1(FC_BOOL_RET, COMModule::IsResource, ReflectModuleBaseObject* pModuleUNSAFE)
1100 {
1101     FCALL_CONTRACT;
1102
1103     if (pModuleUNSAFE == NULL)
1104         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1105
1106     FC_RETURN_BOOL(pModuleUNSAFE->GetModule()->IsResource());
1107 }
1108 FCIMPLEND
1109
1110
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)
1116 {
1117     CONTRACTL
1118     {
1119         NOTHROW;
1120         GC_TRIGGERS;
1121         MODE_PREEMPTIVE;
1122     }
1123     CONTRACTL_END;
1124
1125     if (punk)
1126     {
1127         punk->Release();
1128     }
1129 }
1130
1131
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)
1137 {
1138     FCALL_CONTRACT;
1139
1140     return (void*)DReleaseTarget;
1141 }
1142 FCIMPLEND
1143
1144