Don't denormalize enum return values on instance methods on x86. (#23816)
[platform/upstream/coreclr.git] / src / vm / mlinfo.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 // File: mlinfo.cpp
6 // 
7
8 // 
9
10
11 #include "common.h"
12 #include "mlinfo.h"
13 #include "dllimport.h"
14 #include "sigformat.h"
15 #include "eeconfig.h"
16 #include "eehash.h"
17 #include "../dlls/mscorrc/resource.h"
18 #include "mdaassistants.h"
19 #include "typeparse.h"
20 #include "comdelegate.h"
21 #include "olevariant.h"
22 #include "ilmarshalers.h"
23 #include "interoputil.h"
24
25 #ifdef FEATURE_PREJIT
26     #include "dataimage.h"
27 #endif
28
29 #ifdef FEATURE_COMINTEROP
30 #include "comcallablewrapper.h"
31 #include "runtimecallablewrapper.h"
32 #include "dispparammarshaler.h"
33 #include "winrttypenameconverter.h"
34 #endif // FEATURE_COMINTEROP
35
36
37 #ifndef lengthof
38     #define lengthof(rg)    (sizeof(rg)/sizeof(rg[0]))
39 #endif
40
41
42 #ifdef FEATURE_COMINTEROP
43     DEFINE_ASM_QUAL_TYPE_NAME(ENUMERATOR_TO_ENUM_VARIANT_CM_NAME, g_EnumeratorToEnumClassName, g_CorelibAsmName, VER_ASSEMBLYVERSION_STR, g_ECMAKeyToken);
44
45     static const int        ENUMERATOR_TO_ENUM_VARIANT_CM_NAME_LEN    = lengthof(ENUMERATOR_TO_ENUM_VARIANT_CM_NAME);
46     static const char       ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE[]    = {""};
47     static const int        ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE_LEN  = lengthof(ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE);
48
49     DEFINE_ASM_QUAL_TYPE_NAME(COLOR_TRANSLATOR_ASM_QUAL_TYPE_NAME, g_ColorTranslatorClassName, g_DrawingAsmName, VER_ASSEMBLYVERSION_STR, g_FXKeyToken);
50     DEFINE_ASM_QUAL_TYPE_NAME(COLOR_ASM_QUAL_TYPE_NAME, g_ColorClassName, g_DrawingAsmName, VER_ASSEMBLYVERSION_STR, g_FXKeyToken);
51
52     DEFINE_ASM_QUAL_TYPE_NAME(URI_ASM_QUAL_TYPE_NAME, g_SystemUriClassName, g_SystemRuntimeAsmName, VER_ASSEMBLYVERSION_STR, g_FXKeyToken);
53
54     DEFINE_ASM_QUAL_TYPE_NAME(NCCEVENTARGS_ASM_QUAL_TYPE_NAME, g_NotifyCollectionChangedEventArgsName, g_ObjectModelAsmName, VER_ASSEMBLYVERSION_STR, g_FXKeyToken);
55     DEFINE_ASM_QUAL_TYPE_NAME(NCCEVENTARGS_MARSHALER_ASM_QUAL_TYPE_NAME, g_NotifyCollectionChangedEventArgsMarshalerName, g_SystemRuntimeWindowsRuntimeAsmName, VER_ASSEMBLYVERSION_STR, g_ECMAKeyToken);
56
57
58     DEFINE_ASM_QUAL_TYPE_NAME(PCEVENTARGS_ASM_QUAL_TYPE_NAME, g_PropertyChangedEventArgsName, g_ObjectModelAsmName, VER_ASSEMBLYVERSION_STR, g_FXKeyToken);
59     DEFINE_ASM_QUAL_TYPE_NAME(PCEVENTARGS_MARSHALER_ASM_QUAL_TYPE_NAME, g_PropertyChangedEventArgsMarshalerName, g_SystemRuntimeWindowsRuntimeAsmName, VER_ASSEMBLYVERSION_STR, g_ECMAKeyToken);
60
61
62     #define OLECOLOR_TO_SYSTEMCOLOR_METH_NAME   "FromOle"
63     #define SYSTEMCOLOR_TO_OLECOLOR_METH_NAME   "ToOle"
64
65     #define EVENTARGS_TO_WINRT_EVENTARGS_METH_NAME  "ConvertToNative"
66     #define WINRT_EVENTARGS_TO_EVENTARGS_METH_NAME  "ConvertToManaged"
67
68     #define ORIGINALSTRING_PROPERTY_NAME        "OriginalString"
69 #endif // FEATURE_COMINTEROP
70
71
72
73 #define INITIAL_NUM_CMHELPER_HASHTABLE_BUCKETS 32
74 #define INITIAL_NUM_CMINFO_HASHTABLE_BUCKETS 32
75 #define DEBUG_CONTEXT_STR_LEN 2000
76
77
78 //-------------------------------------------------------------------------------------
79 // Return the copy ctor for a VC class (if any exists)
80 //-------------------------------------------------------------------------------------
81 void FindCopyCtor(Module *pModule, MethodTable *pMT, MethodDesc **pMDOut)
82 {
83     CONTRACTL
84     {
85         THROWS;
86         GC_TRIGGERS;    // CompareTypeTokens may trigger GC
87         MODE_ANY;
88     }
89     CONTRACTL_END;
90         
91     *pMDOut = NULL;
92     
93     HRESULT     hr;
94     mdMethodDef tk;
95     mdTypeDef cl = pMT->GetCl();
96     TypeHandle th = TypeHandle(pMT);
97     SigTypeContext typeContext(th); 
98     
99     IMDInternalImport *pInternalImport = pModule->GetMDImport();
100     MDEnumHolder      hEnumMethod(pInternalImport);
101     
102     //
103     // First try for the new syntax: <MarshalCopy>
104     //
105     IfFailThrow(pInternalImport->EnumInit(mdtMethodDef, cl, &hEnumMethod));
106     
107     while (pInternalImport->EnumNext(&hEnumMethod, &tk))
108     {
109         _ASSERTE(TypeFromToken(tk) == mdtMethodDef);
110         DWORD dwMemberAttrs;
111         IfFailThrow(pInternalImport->GetMethodDefProps(tk, &dwMemberAttrs));
112         
113         if (IsMdSpecialName(dwMemberAttrs))
114         {
115             ULONG cSig;
116             PCCOR_SIGNATURE pSig;
117             LPCSTR pName;
118             IfFailThrow(pInternalImport->GetNameAndSigOfMethodDef(tk, &pSig, &cSig, &pName));
119             
120             const char *pBaseName = "<MarshalCopy>";
121             int ncBaseName = (int)strlen(pBaseName);
122             int nc = (int)strlen(pName);
123             if (nc >= ncBaseName && 0 == strcmp(pName + nc - ncBaseName, pBaseName))
124             {
125                 MetaSig msig(pSig, cSig, pModule, &typeContext);
126                 
127                 // Looking for the prototype   void <MarshalCopy>(Ptr VC, Ptr VC);
128                 if (msig.NumFixedArgs() == 2)
129                 {
130                     if (msig.GetReturnType() == ELEMENT_TYPE_VOID)
131                     {
132                         if (msig.NextArg() == ELEMENT_TYPE_PTR)
133                         {
134                             SigPointer sp1 = msig.GetArgProps();
135                             IfFailThrow(sp1.GetElemType(NULL));
136                             CorElementType eType;
137                             IfFailThrow(sp1.GetElemType(&eType));
138                             if (eType == ELEMENT_TYPE_VALUETYPE)
139                             {
140                                 mdToken tk1;
141                                 IfFailThrow(sp1.GetToken(&tk1));
142                                 hr = CompareTypeTokensNT(tk1, cl, pModule, pModule);
143                                 if (FAILED(hr))
144                                 {
145                                     pInternalImport->EnumClose(&hEnumMethod);
146                                     ThrowHR(hr);
147                                 }
148
149                                 if (hr == S_OK)
150                                 {
151                                     if (msig.NextArg() == ELEMENT_TYPE_PTR)
152                                     {
153                                         SigPointer sp2 = msig.GetArgProps();
154                                         IfFailThrow(sp2.GetElemType(NULL));
155                                         IfFailThrow(sp2.GetElemType(&eType));
156                                         if (eType == ELEMENT_TYPE_VALUETYPE)
157                                         {
158                                             mdToken tk2;
159                                             IfFailThrow(sp2.GetToken(&tk2));
160                                             
161                                             hr = (tk2 == tk1) ? S_OK : CompareTypeTokensNT(tk2, cl, pModule, pModule);
162                                             if (hr == S_OK)
163                                             {
164                                                 *pMDOut = pModule->LookupMethodDef(tk);
165                                                 return;                                 
166                                             }
167                                         }
168                                     }
169                                 }
170                             }
171                         }
172                     }
173                 }
174             }
175         }        
176     }
177
178     //
179     // Next try the old syntax: global .__ctor
180     //
181     IfFailThrow(pInternalImport->EnumGlobalFunctionsInit(&hEnumMethod));
182     
183     while (pInternalImport->EnumNext(&hEnumMethod, &tk))
184     {
185         _ASSERTE(TypeFromToken(tk) == mdtMethodDef);
186         DWORD dwMemberAttrs;
187         IfFailThrow(pInternalImport->GetMethodDefProps(tk, &dwMemberAttrs));
188         
189         if (IsMdSpecialName(dwMemberAttrs))
190         {
191             ULONG cSig;
192             PCCOR_SIGNATURE pSig;
193             LPCSTR pName;
194             IfFailThrow(pInternalImport->GetNameAndSigOfMethodDef(tk, &pSig, &cSig, &pName));
195             
196             const char *pBaseName = ".__ctor";
197             int ncBaseName = (int)strlen(pBaseName);
198             int nc = (int)strlen(pName);
199             if (nc >= ncBaseName && 0 == strcmp(pName + nc - ncBaseName, pBaseName))
200             {
201
202                 MetaSig msig(pSig, cSig, pModule, &typeContext);
203                 
204                 // Looking for the prototype   Ptr VC __ctor(Ptr VC, ByRef VC);
205                 if (msig.NumFixedArgs() == 2)
206                 {
207                     if (msig.GetReturnType() == ELEMENT_TYPE_PTR)
208                     {
209                         SigPointer spret = msig.GetReturnProps();
210                         IfFailThrow(spret.GetElemType(NULL));
211                         CorElementType eType;
212                         IfFailThrow(spret.GetElemType(&eType));
213                         if (eType == ELEMENT_TYPE_VALUETYPE)
214                         {
215                             mdToken tk0;
216                             IfFailThrow(spret.GetToken(&tk0));
217                             hr = CompareTypeTokensNT(tk0, cl, pModule, pModule);
218                             if (FAILED(hr))
219                             {
220                                 pInternalImport->EnumClose(&hEnumMethod);
221                                 ThrowHR(hr);
222                             }
223                             
224                             if (hr == S_OK)
225                             {
226                                 if (msig.NextArg() == ELEMENT_TYPE_PTR)
227                                 {
228                                     SigPointer sp1 = msig.GetArgProps();
229                                     IfFailThrow(sp1.GetElemType(NULL));
230                                     IfFailThrow(sp1.GetElemType(&eType));
231                                     if (eType == ELEMENT_TYPE_VALUETYPE)
232                                     {
233                                         mdToken tk1;
234                                         IfFailThrow(sp1.GetToken(&tk1));
235                                         hr = (tk1 == tk0) ? S_OK : CompareTypeTokensNT(tk1, cl, pModule, pModule);
236                                         if (FAILED(hr))
237                                         {
238                                             pInternalImport->EnumClose(&hEnumMethod);
239                                             ThrowHR(hr);
240                                         }
241
242                                         if (hr == S_OK)
243                                         {
244                                             if (msig.NextArg() == ELEMENT_TYPE_PTR &&
245                                                 msig.GetArgProps().HasCustomModifier(pModule, "Microsoft.VisualC.IsCXXReferenceModifier", ELEMENT_TYPE_CMOD_OPT))
246                                             {
247                                                 SigPointer sp2 = msig.GetArgProps();
248                                                 IfFailThrow(sp2.GetElemType(NULL));
249                                                 IfFailThrow(sp2.GetElemType(&eType));
250                                                 if (eType == ELEMENT_TYPE_VALUETYPE)
251                                                 {
252                                                     mdToken tk2;
253                                                     IfFailThrow(sp2.GetToken(&tk2));
254                                                     
255                                                     hr = (tk2 == tk0) ? S_OK : CompareTypeTokensNT(tk2, cl, pModule, pModule);
256                                                     if (hr == S_OK)
257                                                     {
258                                                         *pMDOut = pModule->LookupMethodDef(tk);
259                                                         return;                                 
260                                                     }
261                                                 }
262                                             }
263                                         }
264                                     }
265                                 }
266                             }
267                         }
268                     }
269                 }
270             }
271         }
272     }
273 }
274
275
276 //-------------------------------------------------------------------------------------
277 // Return the destructor for a VC class (if any exists)
278 //-------------------------------------------------------------------------------------
279 void FindDtor(Module *pModule, MethodTable *pMT, MethodDesc **pMDOut)
280 {
281     CONTRACTL
282     {
283         THROWS;
284         GC_TRIGGERS;    // CompareTypeTokens may trigger GC
285         MODE_ANY;
286     }
287     CONTRACTL_END;
288     
289     *pMDOut = NULL;
290     
291     HRESULT     hr;
292     mdMethodDef tk;
293     mdTypeDef cl = pMT->GetCl();
294     TypeHandle th = TypeHandle(pMT);
295     SigTypeContext typeContext(th);
296     
297     IMDInternalImport *pInternalImport = pModule->GetMDImport();
298     MDEnumHolder       hEnumMethod(pInternalImport);
299     
300     //
301     // First try for the new syntax: <MarshalDestroy>
302     //
303     IfFailThrow(pInternalImport->EnumInit(mdtMethodDef, cl, &hEnumMethod));
304     
305     while (pInternalImport->EnumNext(&hEnumMethod, &tk))
306     {
307         _ASSERTE(TypeFromToken(tk) == mdtMethodDef);
308         DWORD dwMemberAttrs;
309         IfFailThrow(pInternalImport->GetMethodDefProps(tk, &dwMemberAttrs));
310         
311         if (IsMdSpecialName(dwMemberAttrs))
312         {
313             ULONG cSig;
314             PCCOR_SIGNATURE pSig;
315             LPCSTR pName;
316             IfFailThrow(pInternalImport->GetNameAndSigOfMethodDef(tk, &pSig, &cSig, &pName));
317             
318             const char *pBaseName = "<MarshalDestroy>";
319             int ncBaseName = (int)strlen(pBaseName);
320             int nc = (int)strlen(pName);
321             if (nc >= ncBaseName && 0 == strcmp(pName + nc - ncBaseName, pBaseName))
322             {
323                 MetaSig msig(pSig, cSig, pModule, &typeContext);
324                 
325                 // Looking for the prototype   void <MarshalDestroy>(Ptr VC);
326                 if (msig.NumFixedArgs() == 1)
327                 {
328                     if (msig.GetReturnType() == ELEMENT_TYPE_VOID)
329                     {
330                         if (msig.NextArg() == ELEMENT_TYPE_PTR)
331                         {
332                             SigPointer sp1 = msig.GetArgProps();
333                             IfFailThrow(sp1.GetElemType(NULL));
334                             CorElementType eType;
335                             IfFailThrow(sp1.GetElemType(&eType));
336                             if (eType == ELEMENT_TYPE_VALUETYPE)
337                             {
338                                 mdToken tk1;
339                                 IfFailThrow(sp1.GetToken(&tk1));
340                                 
341                                 hr = CompareTypeTokensNT(tk1, cl, pModule, pModule);
342                                 IfFailThrow(hr);
343                                 
344                                 if (hr == S_OK)
345                                 {
346                                     *pMDOut = pModule->LookupMethodDef(tk);
347                                     return;
348                                 }
349                             }
350                         }
351                     }
352                 }
353             }
354         }        
355     }
356
357
358     //
359     // Next try the old syntax: global .__dtor
360     //
361     IfFailThrow(pInternalImport->EnumGlobalFunctionsInit(&hEnumMethod));
362     
363     while (pInternalImport->EnumNext(&hEnumMethod, &tk))
364     {
365         _ASSERTE(TypeFromToken(tk) == mdtMethodDef);
366         ULONG cSig;
367         PCCOR_SIGNATURE pSig;
368         LPCSTR pName;
369         IfFailThrow(pInternalImport->GetNameAndSigOfMethodDef(tk, &pSig, &cSig, &pName));
370         
371         const char *pBaseName = ".__dtor";
372         int ncBaseName = (int)strlen(pBaseName);
373         int nc = (int)strlen(pName);
374         if (nc >= ncBaseName && 0 == strcmp(pName + nc - ncBaseName, pBaseName))
375         {
376             MetaSig msig(pSig, cSig, pModule, &typeContext);
377             
378             // Looking for the prototype   void __dtor(Ptr VC);
379             if (msig.NumFixedArgs() == 1)
380             {
381                 if (msig.GetReturnType() == ELEMENT_TYPE_VOID)
382                 {
383                     if (msig.NextArg() == ELEMENT_TYPE_PTR)
384                     {
385                         SigPointer sp1 = msig.GetArgProps();
386                         IfFailThrow(sp1.GetElemType(NULL));
387                         CorElementType eType;
388                         IfFailThrow(sp1.GetElemType(&eType));
389                         if (eType == ELEMENT_TYPE_VALUETYPE)
390                         {
391                             mdToken tk1;
392                             IfFailThrow(sp1.GetToken(&tk1));
393                             hr = CompareTypeTokensNT(tk1, cl, pModule, pModule);
394                             if (FAILED(hr))
395                             {
396                                 pInternalImport->EnumClose(&hEnumMethod);
397                                 ThrowHR(hr);
398                             }
399                             
400                             if (hr == S_OK)
401                             {
402                                 *pMDOut = pModule->LookupMethodDef(tk);
403                                 return;
404                             }
405                         }
406                     }
407                 }
408             }
409         }
410     }
411 }
412
413 //==========================================================================
414 // Set's up the custom marshaler information.
415 //==========================================================================
416 CustomMarshalerHelper *SetupCustomMarshalerHelper(LPCUTF8 strMarshalerTypeName, DWORD cMarshalerTypeNameBytes, LPCUTF8 strCookie, DWORD cCookieStrBytes, Assembly *pAssembly, TypeHandle hndManagedType)
417 {
418 #ifndef CROSSGEN_COMPILE
419     CONTRACT (CustomMarshalerHelper*)
420     {
421         THROWS;
422         GC_TRIGGERS;
423         MODE_ANY;
424         PRECONDITION(CheckPointer(pAssembly));
425         POSTCONDITION(CheckPointer(RETVAL));
426     }
427     CONTRACT_END;
428     
429     EEMarshalingData *pMarshalingData = NULL;
430
431     // The assembly is not shared so we use the current app domain's marshaling data.
432     pMarshalingData = pAssembly->GetLoaderAllocator()->GetMarshalingData();
433
434     // Retrieve the custom marshaler helper from the EE marshaling data.
435     RETURN pMarshalingData->GetCustomMarshalerHelper(pAssembly, hndManagedType, strMarshalerTypeName, cMarshalerTypeNameBytes, strCookie, cCookieStrBytes);
436 #else
437     _ASSERTE(false);
438     RETURN NULL;
439 #endif
440 }
441
442 //==========================================================================
443 // Return: S_OK if there is valid data to compress
444 //         S_FALSE if at end of data block
445 //         E_FAIL if corrupt data found
446 //==========================================================================
447 HRESULT CheckForCompressedData(PCCOR_SIGNATURE pvNativeTypeStart, PCCOR_SIGNATURE pvNativeType, ULONG cbNativeType)
448 {
449     CONTRACTL
450     {
451         NOTHROW;
452         GC_NOTRIGGER;
453         MODE_ANY;
454     }
455     CONTRACTL_END;
456
457     if (pvNativeTypeStart + cbNativeType == pvNativeType)
458     {   // end of data block
459         return S_FALSE;
460     }
461
462     ULONG ulDummy;
463     BYTE const *pbDummy;
464     return CPackedLen::SafeGetLength((BYTE const *)pvNativeType,
465                                      (BYTE const *)pvNativeTypeStart + cbNativeType,
466                                      &ulDummy,
467                                      &pbDummy);
468 }
469
470 //==========================================================================
471 // Parse and validate the NATIVE_TYPE_ metadata.
472 // Note! NATIVE_TYPE_ metadata is optional. If it's not present, this
473 // routine sets NativeTypeParamInfo->m_NativeType to NATIVE_TYPE_DEFAULT. 
474 //==========================================================================
475 BOOL ParseNativeTypeInfo(NativeTypeParamInfo* pParamInfo, PCCOR_SIGNATURE pvNativeType, ULONG cbNativeType);
476
477 BOOL ParseNativeTypeInfo(mdToken                    token,
478                          IMDInternalImport*         pScope,
479                          NativeTypeParamInfo*       pParamInfo)
480 {
481     CONTRACTL
482     {
483         NOTHROW;
484         GC_NOTRIGGER;
485         MODE_ANY;
486     }
487     CONTRACTL_END;
488     
489     PCCOR_SIGNATURE pvNativeType;
490     ULONG           cbNativeType;
491
492     if (token == mdParamDefNil || pScope->GetFieldMarshal(token, &pvNativeType, &cbNativeType) != S_OK)
493         return TRUE;
494
495     return ParseNativeTypeInfo(pParamInfo, pvNativeType, cbNativeType);
496 }
497
498 BOOL ParseNativeTypeInfo(NativeTypeParamInfo* pParamInfo,
499                          PCCOR_SIGNATURE pvNativeType,
500                          ULONG cbNativeType)
501 {
502     LIMITED_METHOD_CONTRACT;
503     HRESULT hr;
504
505     PCCOR_SIGNATURE pvNativeTypeStart = pvNativeType;
506     PCCOR_SIGNATURE pvNativeTypeEnd = pvNativeType + cbNativeType;
507
508     if (cbNativeType == 0)
509         return FALSE;  // Zero-length NATIVE_TYPE block
510
511     pParamInfo->m_NativeType = (CorNativeType)*(pvNativeType++);
512     ULONG strLen = 0;
513
514     // Retrieve any extra information associated with the native type.
515     switch (pParamInfo->m_NativeType)
516     {
517 #ifdef FEATURE_COMINTEROP
518         case NATIVE_TYPE_INTF:
519         case NATIVE_TYPE_IUNKNOWN:
520         case NATIVE_TYPE_IDISPATCH:
521             if (S_OK != CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType))
522                 return TRUE;
523             
524             pParamInfo->m_IidParamIndex = (int)CorSigUncompressData(pvNativeType);
525             break;
526 #endif
527             
528         case NATIVE_TYPE_FIXEDARRAY:
529             
530             if (S_OK != CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType))
531                 return FALSE; 
532
533             pParamInfo->m_Additive = CorSigUncompressData(pvNativeType);
534             
535             if (S_OK != CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType))
536                 return TRUE;
537
538             pParamInfo->m_ArrayElementType = (CorNativeType)CorSigUncompressData(pvNativeType);                
539             break;
540             
541         case NATIVE_TYPE_FIXEDSYSSTRING:
542             if (S_OK != CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType))
543                 return FALSE; 
544
545             pParamInfo->m_Additive = CorSigUncompressData(pvNativeType);
546             break;
547             
548 #ifdef FEATURE_COMINTEROP
549         case NATIVE_TYPE_SAFEARRAY:
550             // Check for the safe array element type.
551             hr = CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType);
552             if (FAILED(hr))
553                 return FALSE;
554
555             if (hr == S_OK)
556                 pParamInfo->m_SafeArrayElementVT = (VARTYPE) (CorSigUncompressData(/*modifies*/pvNativeType));
557
558             // Extract the name of the record type's.
559             if (S_OK == CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType))
560             {
561                 hr = CPackedLen::SafeGetData((BYTE const *)pvNativeType,
562                                              (BYTE const *)pvNativeTypeEnd,
563                                              &strLen,
564                                              (BYTE const **)&pvNativeType);
565                 if (FAILED(hr))
566                 {
567                     return FALSE;
568                 }
569
570                 pParamInfo->m_strSafeArrayUserDefTypeName = (LPUTF8)pvNativeType;
571                 pParamInfo->m_cSafeArrayUserDefTypeNameBytes = strLen;
572                 _ASSERTE((ULONG)(pvNativeType + strLen - pvNativeTypeStart) == cbNativeType);
573             }
574             break;
575
576 #endif // FEATURE_COMINTEROP
577
578         case NATIVE_TYPE_ARRAY:
579             hr = CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType);
580             if (FAILED(hr))
581                 return FALSE;
582
583             if (hr == S_OK)
584                 pParamInfo->m_ArrayElementType = (CorNativeType) (CorSigUncompressData(/*modifies*/pvNativeType));
585
586             // Check for "sizeis" param index
587             hr = CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType);
588             if (FAILED(hr))
589                 return FALSE;
590
591             if (hr == S_OK)
592             {
593                 pParamInfo->m_SizeIsSpecified = TRUE;
594                 pParamInfo->m_CountParamIdx = (UINT16)(CorSigUncompressData(/*modifies*/pvNativeType));
595
596                 // If an "sizeis" param index is present, the defaults for multiplier and additive change
597                 pParamInfo->m_Multiplier = 1;
598                 pParamInfo->m_Additive   = 0;
599
600                 // Check for "sizeis" additive
601                 hr = CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType);
602                 if (FAILED(hr))
603                     return FALSE;
604
605                 if (hr == S_OK)
606                 {
607                     // Extract the additive.
608                     pParamInfo->m_Additive = (DWORD)CorSigUncompressData(/*modifies*/pvNativeType);
609
610                     // Check to see if the flags field is present. 
611                     hr = CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType);
612                     if (FAILED(hr))
613                         return FALSE;
614
615                     if (hr == S_OK)
616                     {
617                         // If the param index specified flag isn't set then we need to reset the
618                         // multiplier to 0 to indicate no size param index was specified.
619                         NativeTypeArrayFlags flags = (NativeTypeArrayFlags)CorSigUncompressData(/*modifies*/pvNativeType);;
620                         if (!(flags & ntaSizeParamIndexSpecified))
621                             pParamInfo->m_Multiplier = 0;
622                     }
623                 }
624             }
625
626             break;
627
628         case NATIVE_TYPE_CUSTOMMARSHALER:
629             // Skip the typelib guid.
630             if (S_OK != CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType))
631                 return FALSE;
632
633             if (FAILED(CPackedLen::SafeGetData(pvNativeType, pvNativeTypeEnd, &strLen, (void const **)&pvNativeType)))
634                 return FALSE;
635
636             pvNativeType += strLen;
637             _ASSERTE((ULONG)(pvNativeType - pvNativeTypeStart) < cbNativeType);                
638
639             // Skip the name of the native type.
640             if (S_OK != CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType))
641                 return FALSE;
642
643             if (FAILED(CPackedLen::SafeGetData(pvNativeType, pvNativeTypeEnd, &strLen, (void const **)&pvNativeType)))
644                 return FALSE;
645
646             pvNativeType += strLen;
647             _ASSERTE((ULONG)(pvNativeType - pvNativeTypeStart) < cbNativeType);
648
649             // Extract the name of the custom marshaler.
650             if (S_OK != CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType))
651                 return FALSE;
652
653             if (FAILED(CPackedLen::SafeGetData(pvNativeType, pvNativeTypeEnd, &strLen, (void const **)&pvNativeType)))
654                 return FALSE;
655
656             pParamInfo->m_strCMMarshalerTypeName = (LPUTF8)pvNativeType;
657             pParamInfo->m_cCMMarshalerTypeNameBytes = strLen;
658             pvNativeType += strLen;
659             _ASSERTE((ULONG)(pvNativeType - pvNativeTypeStart) < cbNativeType);
660
661             // Extract the cookie string.
662             if (S_OK != CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType))
663                 return FALSE;
664
665             if (FAILED(CPackedLen::SafeGetData(pvNativeType, pvNativeTypeEnd, &strLen, (void const **)&pvNativeType)))
666                 return FALSE;
667
668             pParamInfo->m_strCMCookie = (LPUTF8)pvNativeType;
669             pParamInfo->m_cCMCookieStrBytes = strLen;
670             _ASSERTE((ULONG)(pvNativeType + strLen - pvNativeTypeStart) == cbNativeType);
671             break;
672
673         default:
674             break;
675     }
676
677     return TRUE;
678 }
679
680 //==========================================================================
681 // Determines whether *pManagedElemType is really normalized (i.e. differs
682 // from what sigPtr points to modulo generic instantiation). If it is the
683 // case, all types that have been normalized away are checked for valid
684 // managed/unmanaged type combination, and *pNativeType is updated to contain
685 // the native type of the primitive type field inside. On error (a generic
686 // type is encountered or managed/unmanaged type mismatch) or non-default
687 // native type of the primitive type inside, *pManagedElemType is un-normalized
688 // so that the calling code can deal with the situation in its own way.
689 //==========================================================================
690 void VerifyAndAdjustNormalizedType(
691                          Module *                   pModule,
692                          SigPointer                 sigPtr,
693                          const SigTypeContext *     pTypeContext,
694                          CorElementType *           pManagedElemType,
695                          CorNativeType *            pNativeType)
696 {
697     CorElementType sigElemType = sigPtr.PeekElemTypeClosed(pModule, pTypeContext);
698
699     if (*pManagedElemType != sigElemType)
700     {
701         // Normalized element type differs from closed element type, which means that
702         // normalization has occurred.
703         _ASSERTE(sigElemType == ELEMENT_TYPE_VALUETYPE);
704
705         // Now we know that this is a normalized value type - we have to verify the removed
706         // value type(s) and get to the true primitive type inside.
707         TypeHandle th = sigPtr.GetTypeHandleThrowing(pModule,
708                                                      pTypeContext,
709                                                      ClassLoader::LoadTypes,
710                                                      CLASS_LOAD_UNRESTORED,
711                                                      TRUE);
712         _ASSERTE(!th.IsNull() && !th.IsTypeDesc());
713
714         CorNativeType ntype = *pNativeType;
715
716         if (!th.AsMethodTable()->IsTruePrimitive() &&
717             !th.IsEnum())
718         {
719             // This is a trivial (yet non-primitive) value type that has been normalized.
720             // Loop until we eventually hit the primitive type or enum inside.
721             do
722             {
723                 if (th.HasInstantiation())
724                 {
725                     // generic structures are either not marshalable or special-cased - the caller needs to know either way
726                     *pManagedElemType = sigElemType;
727                     return;
728                 }
729
730                 // verify the native type of the value type (must be default or Struct)
731                 if (!(ntype == NATIVE_TYPE_DEFAULT || ntype == NATIVE_TYPE_STRUCT))
732                 {
733                     *pManagedElemType = sigElemType;
734                     return;
735                 }
736
737                 MethodTable *pMT = th.GetMethodTable();
738                 _ASSERTE(pMT != NULL && pMT->IsValueType() && pMT->GetNumInstanceFields() == 1);
739
740                 // get the only instance field
741                 PTR_FieldDesc fieldDesc = pMT->GetApproxFieldDescListRaw();
742
743                 // retrieve the MarshalAs of the field
744                 NativeTypeParamInfo paramInfo;
745                 if (!ParseNativeTypeInfo(fieldDesc->GetMemberDef(), th.GetModule()->GetMDImport(), &paramInfo))
746                 {
747                     *pManagedElemType = sigElemType;
748                     return;
749                 }
750
751                 ntype = paramInfo.m_NativeType;
752
753                 th = fieldDesc->GetApproxFieldTypeHandleThrowing();
754             }
755             while (!th.IsTypeDesc() &&
756                    !th.AsMethodTable()->IsTruePrimitive() &&
757                    !th.IsEnum());
758
759             // now ntype contains the native type of *pManagedElemType
760             if (ntype == NATIVE_TYPE_DEFAULT)
761             {
762                 // Let's update the caller's native type with default type only.
763                 // Updating with a non-default native type that is not allowed
764                 // for the given managed type would result in confusing exception
765                 // messages.
766                 *pNativeType = ntype;
767             }
768             else
769             {
770                 *pManagedElemType = sigElemType;
771             }
772         }
773     }
774 }
775
776 VOID ThrowInteropParamException(UINT resID, UINT paramIdx)
777 {
778     CONTRACTL
779     {
780         THROWS;
781         GC_TRIGGERS;
782         MODE_ANY;
783     }
784     CONTRACTL_END;
785     
786     SString paramString;
787     if (paramIdx == 0)
788         paramString.Set(W("return value"));
789     else
790         paramString.Printf(W("parameter #%u"), paramIdx);
791
792     SString errorString(W("Unknown error."));
793     errorString.LoadResource(CCompRC::Error, resID);
794     
795     COMPlusThrow(kMarshalDirectiveException, IDS_EE_BADMARSHAL_ERROR_MSG, paramString.GetUnicode(), errorString.GetUnicode());
796 }
797
798 //===============================================================
799 // Collects paraminfo's in an indexed array so that:
800 //
801 //   aParams[0] == param token for return value
802 //   aParams[1] == param token for argument #1...
803 //   aParams[numargs] == param token for argument #n...
804 //
805 // If no param token exists, the corresponding array element
806 // is set to mdParamDefNil.
807 //
808 // Inputs:
809 //    pInternalImport  -- ifc for metadata api
810 //    md       -- token of method. If token is mdMethodNil,
811 //                all aParam elements will be set to mdParamDefNil.
812 //    numargs  -- # of arguments in mdMethod
813 //    aParams  -- uninitialized array with numargs+1 elements.
814 //                on exit, will be filled with param tokens.
815 //===============================================================
816 VOID CollateParamTokens(IMDInternalImport *pInternalImport, mdMethodDef md, ULONG numargs, mdParamDef *aParams)
817 {
818     CONTRACTL
819     {
820         THROWS;
821         GC_NOTRIGGER;
822         MODE_ANY;
823     }
824     CONTRACTL_END;
825     
826     for (ULONG i = 0; i < numargs + 1; i++)
827         aParams[i] = mdParamDefNil;
828
829     if (md != mdMethodDefNil)
830     {
831         MDEnumHolder hEnumParams(pInternalImport);
832         HRESULT hr = pInternalImport->EnumInit(mdtParamDef, md, &hEnumParams);
833         if (FAILED(hr))
834         {
835             // no param info: nothing left to do here
836         }
837         else
838         {
839             mdParamDef CurrParam = mdParamDefNil;
840             while (pInternalImport->EnumNext(&hEnumParams, &CurrParam))
841             {
842                 USHORT usSequence;
843                 DWORD dwAttr;
844                 LPCSTR szParamName_Ignore;
845                 if (SUCCEEDED(pInternalImport->GetParamDefProps(CurrParam, &usSequence, &dwAttr, &szParamName_Ignore)))
846                 {
847                     if (usSequence > numargs)
848                     {   // Invalid argument index
849                         ThrowHR(COR_E_BADIMAGEFORMAT);
850                     }
851                     if (aParams[usSequence] != mdParamDefNil)
852                     {   // Duplicit argument index
853                         ThrowHR(COR_E_BADIMAGEFORMAT);
854                     }
855                     aParams[usSequence] = CurrParam;
856                 }
857             }
858         }
859     }
860 }
861
862
863 #ifdef FEATURE_COMINTEROP
864
865 void *EventArgsMarshalingInfo::operator new(size_t size, LoaderHeap *pHeap)
866 {
867     CONTRACT (void*)
868     {
869         THROWS;
870         GC_NOTRIGGER;
871         MODE_ANY;
872         INJECT_FAULT(COMPlusThrowOM());
873         PRECONDITION(CheckPointer(pHeap));
874         POSTCONDITION(CheckPointer(RETVAL));
875     }
876     CONTRACT_END;
877     
878     void* mem = pHeap->AllocMem(S_SIZE_T(size));
879
880     RETURN mem;
881 }
882
883 void EventArgsMarshalingInfo::operator delete(void *pMem)
884 {
885     LIMITED_METHOD_CONTRACT;
886     // Instances of this class are always allocated on the loader heap so
887     // the delete operator has nothing to do.
888 }
889
890 EventArgsMarshalingInfo::EventArgsMarshalingInfo()
891 {
892     CONTRACTL
893     {
894         THROWS;
895         GC_TRIGGERS;
896         MODE_ANY;
897     }
898     CONTRACTL_END;
899
900     // Load the System.Collections.Specialized.NotifyCollectionChangedEventArgs class.
901     SString qualifiedNCCEventArgsTypeName(SString::Utf8, NCCEVENTARGS_ASM_QUAL_TYPE_NAME);
902     m_hndSystemNCCEventArgsType = TypeName::GetTypeFromAsmQualifiedName(qualifiedNCCEventArgsTypeName.GetUnicode());
903     _ASSERTE(!m_hndSystemNCCEventArgsType.IsNull() && "Cannot load System.Collections.Specialized.NotifyCollectionChangedEventArgs!");
904
905     // Load the System.ComponentModel.PropertyChangedEventArgs class.
906     SString qualifiedPCEventArgsTypeName(SString::Utf8, PCEVENTARGS_ASM_QUAL_TYPE_NAME);
907     m_hndSystemPCEventArgsType = TypeName::GetTypeFromAsmQualifiedName(qualifiedPCEventArgsTypeName.GetUnicode());
908     _ASSERTE(!m_hndSystemPCEventArgsType.IsNull() && "Cannot load System.ComponentModel.PropertyChangedEventArgs!");
909
910     // Load the NCCEventArgs marshaler class.
911     SString qualifiedNCCEventArgsMarshalerTypeName(SString::Utf8, NCCEVENTARGS_MARSHALER_ASM_QUAL_TYPE_NAME);
912     TypeHandle hndNCCEventArgsMarshalerType = TypeName::GetTypeFromAsmQualifiedName(qualifiedNCCEventArgsMarshalerTypeName.GetUnicode());
913
914     // Retrieve the method to convert a .NET NCCEventArgs to a WinRT NCCEventArgs.
915     m_pSystemNCCEventArgsToWinRTNCCEventArgsMD = MemberLoader::FindMethodByName(hndNCCEventArgsMarshalerType.GetMethodTable(), EVENTARGS_TO_WINRT_EVENTARGS_METH_NAME);
916     _ASSERTE(m_pSystemNCCEventArgsToWinRTNCCEventArgsMD && "Unable to find the marshaler method to convert a .NET NCCEventArgs to a WinRT NCCEventArgs!");
917
918     // Retrieve the method to convert a WinRT NCCEventArgs to a .NET NCCEventArgs.
919     m_pWinRTNCCEventArgsToSystemNCCEventArgsMD = MemberLoader::FindMethodByName(hndNCCEventArgsMarshalerType.GetMethodTable(), WINRT_EVENTARGS_TO_EVENTARGS_METH_NAME);
920     _ASSERTE(m_pWinRTNCCEventArgsToSystemNCCEventArgsMD && "Unable to find the marshaler method to convert a WinRT NCCEventArgs to a .NET NCCEventArgs!");
921
922     // Load the PCEventArgs marshaler class.
923     SString qualifiedPCEventArgsMarshalerTypeName(SString::Utf8, PCEVENTARGS_MARSHALER_ASM_QUAL_TYPE_NAME);
924     TypeHandle hndPCEventArgsMarshalerType = TypeName::GetTypeFromAsmQualifiedName(qualifiedPCEventArgsMarshalerTypeName.GetUnicode());
925
926     // Retrieve the method to convert a .NET PCEventArgs to a WinRT PCEventArgs.
927     m_pSystemPCEventArgsToWinRTPCEventArgsMD = MemberLoader::FindMethodByName(hndPCEventArgsMarshalerType.GetMethodTable(), EVENTARGS_TO_WINRT_EVENTARGS_METH_NAME);
928     _ASSERTE(m_pSystemPCEventArgsToWinRTPCEventArgsMD && "Unable to find the marshaler method to convert a .NET PCEventArgs to a WinRT PCEventArgs!");
929
930     // Retrieve the method to convert a WinRT PCEventArgs to a .NET PCEventArgs.
931     m_pWinRTPCEventArgsToSystemPCEventArgsMD = MemberLoader::FindMethodByName(hndPCEventArgsMarshalerType.GetMethodTable(), WINRT_EVENTARGS_TO_EVENTARGS_METH_NAME);
932     _ASSERTE(m_pWinRTPCEventArgsToSystemPCEventArgsMD && "Unable to find the marshaler method to convert a WinRT PCEventArgs to a .NET PCEventArgs!");
933 }
934
935 EventArgsMarshalingInfo::~EventArgsMarshalingInfo()
936 {
937    LIMITED_METHOD_CONTRACT;
938 }
939
940 void *UriMarshalingInfo::operator new(size_t size, LoaderHeap *pHeap)
941 {
942     CONTRACT (void*)
943     {
944         THROWS;
945         GC_NOTRIGGER;
946         MODE_ANY;
947         INJECT_FAULT(COMPlusThrowOM());
948         PRECONDITION(CheckPointer(pHeap));
949         POSTCONDITION(CheckPointer(RETVAL));
950     }
951     CONTRACT_END;
952     
953     void* mem = pHeap->AllocMem(S_SIZE_T(size));
954
955     RETURN mem;
956 }
957
958
959 void UriMarshalingInfo::operator delete(void *pMem)
960 {
961     LIMITED_METHOD_CONTRACT;
962     // Instances of this class are always allocated on the loader heap so
963     // the delete operator has nothing to do.
964 }
965
966 UriMarshalingInfo::UriMarshalingInfo()
967 {
968     CONTRACTL
969     {
970         THROWS;
971         GC_TRIGGERS;
972         MODE_ANY;
973     }
974     CONTRACTL_END;
975
976     // Create on-demand as we don't want to create the factories in NGEN time
977     m_pUriFactory = NULL;
978
979     // Load the System.Uri class.
980     SString qualifiedUriTypeName(SString::Utf8, URI_ASM_QUAL_TYPE_NAME);
981     m_hndSystemUriType = TypeName::GetTypeFromAsmQualifiedName(qualifiedUriTypeName.GetUnicode());
982     _ASSERTE(!m_hndSystemUriType.IsNull() && "Cannot load System.Uri!");
983     
984     m_SystemUriOriginalStringGetterMD = MemberLoader::FindPropertyMethod(m_hndSystemUriType.GetMethodTable(), ORIGINALSTRING_PROPERTY_NAME, PropertyGet);
985     _ASSERTE(m_SystemUriOriginalStringGetterMD && "Unable to find the System.Uri.get_OriginalString()!");
986     _ASSERTE(!m_SystemUriOriginalStringGetterMD->IsStatic() && "System.Uri.get_OriginalString() is static!");
987
988     // Windows.Foundation.Uri..ctor(string) and System.Uri..ctor(string)
989     MethodTable* pSystemUriMT = m_hndSystemUriType.AsMethodTable();
990     m_SystemUriCtorMD = MemberLoader::FindConstructor(pSystemUriMT, &gsig_IM_Str_RetVoid);
991     _ASSERTE(m_SystemUriCtorMD && "Unable to find the constructor on System.Uri that takes a string!");
992     _ASSERTE(m_SystemUriCtorMD->IsClassConstructorOrCtor() && !m_SystemUriCtorMD->IsStatic() && "The method retrieved from System.Uri is not a constructor!");
993 }
994
995 UriMarshalingInfo::~UriMarshalingInfo()
996 {
997     CONTRACTL
998     {
999         NOTHROW;
1000         GC_TRIGGERS;
1001         MODE_ANY;
1002     }
1003     CONTRACTL_END;
1004 #ifndef CROSSGEN_COMPILE
1005     if (m_pUriFactory)
1006     {
1007         SafeRelease(m_pUriFactory);
1008         m_pUriFactory = NULL;
1009     }
1010 #endif
1011 }
1012
1013 OleColorMarshalingInfo::OleColorMarshalingInfo() :
1014     m_OleColorToSystemColorMD(NULL),
1015     m_SystemColorToOleColorMD(NULL)
1016 {
1017     CONTRACTL
1018     {
1019         THROWS;
1020         GC_TRIGGERS;
1021         MODE_ANY;
1022     }
1023     CONTRACTL_END;
1024
1025     SString qualifiedColorTranslatorTypeName(SString::Utf8, COLOR_TRANSLATOR_ASM_QUAL_TYPE_NAME);
1026
1027     // Load the color translator class.
1028     TypeHandle hndColorTranslatorType = TypeName::GetTypeFromAsmQualifiedName(qualifiedColorTranslatorTypeName.GetUnicode());
1029
1030     
1031     SString qualifiedColorTypeName(SString::Utf8, COLOR_ASM_QUAL_TYPE_NAME);
1032     // Load the color class.
1033     m_hndColorType = TypeName::GetTypeFromAsmQualifiedName(qualifiedColorTypeName.GetUnicode());
1034     
1035     // Retrieve the method to convert an OLE_COLOR to a System.Drawing.Color.
1036     m_OleColorToSystemColorMD = MemberLoader::FindMethodByName(hndColorTranslatorType.GetMethodTable(), OLECOLOR_TO_SYSTEMCOLOR_METH_NAME);
1037     _ASSERTE(m_OleColorToSystemColorMD && "Unable to find the translator method to convert an OLE_COLOR to a System.Drawing.Color!");
1038     _ASSERTE(m_OleColorToSystemColorMD->IsStatic() && "The translator method to convert an OLE_COLOR to a System.Drawing.Color must be static!");
1039
1040     // Retrieve the method to convert a System.Drawing.Color to an OLE_COLOR.
1041     m_SystemColorToOleColorMD = MemberLoader::FindMethodByName(hndColorTranslatorType.GetMethodTable(), SYSTEMCOLOR_TO_OLECOLOR_METH_NAME);
1042     _ASSERTE(m_SystemColorToOleColorMD && "Unable to find the translator method to convert a System.Drawing.Color to an OLE_COLOR!");
1043     _ASSERTE(m_SystemColorToOleColorMD->IsStatic() && "The translator method to convert a System.Drawing.Color to an OLE_COLOR must be static!");
1044 }
1045
1046
1047 void *OleColorMarshalingInfo::operator new(size_t size, LoaderHeap *pHeap)
1048 {
1049     CONTRACT (void*)
1050     {
1051         THROWS;
1052         GC_NOTRIGGER;
1053         MODE_ANY;
1054         INJECT_FAULT(COMPlusThrowOM());
1055         PRECONDITION(CheckPointer(pHeap));
1056         POSTCONDITION(CheckPointer(RETVAL));
1057     }
1058     CONTRACT_END;
1059     
1060     void* mem = pHeap->AllocMem(S_SIZE_T(size));
1061
1062     RETURN mem;
1063 }
1064
1065
1066 void OleColorMarshalingInfo::operator delete(void *pMem)
1067 {
1068     LIMITED_METHOD_CONTRACT;
1069     // Instances of this class are always allocated on the loader heap so
1070     // the delete operator has nothing to do.
1071 }
1072
1073 #endif // FEATURE_COMINTEROP
1074
1075 EEMarshalingData::EEMarshalingData(LoaderAllocator* pAllocator, CrstBase *pCrst) :
1076     m_pAllocator(pAllocator),
1077     m_pHeap(pAllocator->GetLowFrequencyHeap()),
1078     m_lock(pCrst)
1079 {
1080     CONTRACTL
1081     {
1082         NOTHROW;
1083         GC_NOTRIGGER;
1084         MODE_ANY;
1085     }
1086     CONTRACTL_END;
1087     
1088     LockOwner lock = {pCrst, IsOwnerOfCrst};
1089 #ifndef CROSSGEN_COMPILE
1090     m_CMHelperHashtable.Init(INITIAL_NUM_CMHELPER_HASHTABLE_BUCKETS, &lock);
1091     m_SharedCMHelperToCMInfoMap.Init(INITIAL_NUM_CMINFO_HASHTABLE_BUCKETS, &lock);
1092 #endif // CROSSGEN_COMPILE
1093 }
1094
1095
1096 EEMarshalingData::~EEMarshalingData()
1097 {
1098     WRAPPER_NO_CONTRACT;
1099     
1100     CustomMarshalerInfo *pCMInfo;
1101
1102     // <TODO>@TODO(DM): Remove the linked list of CMInfo's and instead hang the OBJECTHANDLE 
1103     // contained inside the CMInfo off the AppDomain directly. The AppDomain can have
1104     // a list of tasks to do when it gets teared down and we could leverage that
1105     // to release the object handles.</TODO>
1106
1107     // Walk through the linked list and delete all the custom marshaler info's.
1108     while ((pCMInfo = m_pCMInfoList.RemoveHead()) != NULL)
1109         delete pCMInfo;
1110
1111 #ifdef FEATURE_COMINTEROP
1112     if (m_pOleColorInfo)
1113     {
1114         delete m_pOleColorInfo;
1115         m_pOleColorInfo = NULL;
1116     }
1117     
1118     if (m_pUriInfo)
1119     {
1120         delete m_pUriInfo;
1121         m_pUriInfo = NULL;
1122     }
1123     
1124     if (m_pEventArgsInfo)
1125     {
1126         delete m_pEventArgsInfo;
1127         m_pEventArgsInfo = NULL;
1128     }    
1129 #endif
1130 }
1131
1132
1133 void *EEMarshalingData::operator new(size_t size, LoaderHeap *pHeap)
1134 {
1135     CONTRACT (void*)
1136     {
1137         THROWS;
1138         GC_NOTRIGGER;
1139         MODE_ANY;
1140         INJECT_FAULT(COMPlusThrowOM());
1141         PRECONDITION(CheckPointer(pHeap));
1142         POSTCONDITION(CheckPointer(RETVAL));
1143     }
1144     CONTRACT_END;
1145
1146     void* mem = pHeap->AllocMem(S_SIZE_T(sizeof(EEMarshalingData)));
1147
1148     RETURN mem;
1149 }
1150
1151
1152 void EEMarshalingData::operator delete(void *pMem)
1153 {
1154     LIMITED_METHOD_CONTRACT;
1155     // Instances of this class are always allocated on the loader heap so
1156     // the delete operator has nothing to do.
1157 }
1158
1159 #ifndef CROSSGEN_COMPILE
1160
1161 CustomMarshalerHelper *EEMarshalingData::GetCustomMarshalerHelper(Assembly *pAssembly, TypeHandle hndManagedType, LPCUTF8 strMarshalerTypeName, DWORD cMarshalerTypeNameBytes, LPCUTF8 strCookie, DWORD cCookieStrBytes)
1162 {
1163     CONTRACT (CustomMarshalerHelper*)
1164     {
1165         THROWS;
1166         GC_TRIGGERS;
1167         MODE_ANY;
1168         INJECT_FAULT(COMPlusThrowOM());
1169         PRECONDITION(CheckPointer(pAssembly));
1170         POSTCONDITION(CheckPointer(RETVAL));
1171     }
1172     CONTRACT_END;
1173
1174     CustomMarshalerHelper *pCMHelper = NULL;
1175     CustomMarshalerHelper* pNewCMHelper = NULL;
1176     NewHolder<CustomMarshalerInfo> pNewCMInfo(NULL);
1177     
1178     TypeHandle hndCustomMarshalerType;
1179
1180     // Create the key that will be used to lookup in the hashtable.
1181     EECMHelperHashtableKey Key(cMarshalerTypeNameBytes, strMarshalerTypeName, cCookieStrBytes, strCookie, hndManagedType.GetInstantiation(), pAssembly);
1182
1183     // Lookup the custom marshaler helper in the hashtable.
1184     if (m_CMHelperHashtable.GetValue(&Key, (HashDatum*)&pCMHelper))
1185         RETURN pCMHelper;
1186
1187     {
1188         GCX_COOP();
1189
1190         // Validate the arguments.
1191         _ASSERTE(strMarshalerTypeName && strCookie && !hndManagedType.IsNull());
1192
1193         // Append a NULL terminator to the marshaler type name.
1194         SString strCMMarshalerTypeName(SString::Utf8, strMarshalerTypeName, cMarshalerTypeNameBytes);
1195
1196         // Load the custom marshaler class. 
1197         BOOL fNameIsAsmQualified = FALSE;
1198         hndCustomMarshalerType = TypeName::GetTypeUsingCASearchRules(strCMMarshalerTypeName.GetUTF8NoConvert(), pAssembly, &fNameIsAsmQualified);
1199         
1200         if (hndCustomMarshalerType.IsGenericTypeDefinition())
1201         {
1202             // Instantiate generic custom marshalers using the instantiation of the type being marshaled.
1203             hndCustomMarshalerType = hndCustomMarshalerType.Instantiate(hndManagedType.GetInstantiation());
1204         }
1205
1206         // Set the assembly to null to indicate that the custom marshaler name is assembly
1207         // qualified.        
1208         if (fNameIsAsmQualified)
1209             pAssembly = NULL;
1210
1211
1212         // Create the custom marshaler info in the specified heap.
1213         pNewCMInfo = new (m_pHeap) CustomMarshalerInfo(m_pAllocator, hndCustomMarshalerType, hndManagedType, strCookie, cCookieStrBytes);
1214
1215         // Create the custom marshaler helper in the specified heap.
1216         pNewCMHelper = new (m_pHeap) NonSharedCustomMarshalerHelper(pNewCMInfo);
1217     }
1218
1219     {
1220         CrstHolder lock(m_lock);
1221
1222         // Verify that the custom marshaler helper has not already been added by another thread.
1223         if (m_CMHelperHashtable.GetValue(&Key, (HashDatum*)&pCMHelper))
1224         {
1225             RETURN pCMHelper;
1226         }
1227
1228         // Add the custom marshaler helper to the hash table.
1229         m_CMHelperHashtable.InsertValue(&Key, pNewCMHelper, FALSE);
1230
1231         // If we create the CM info, then add it to the linked list.
1232         if (pNewCMInfo)
1233         {
1234             m_pCMInfoList.InsertHead(pNewCMInfo);
1235             pNewCMInfo.SuppressRelease();
1236         }
1237
1238         // Release the lock and return the custom marshaler info.
1239     }
1240
1241     RETURN pNewCMHelper;
1242 }
1243
1244 CustomMarshalerInfo *EEMarshalingData::GetCustomMarshalerInfo(SharedCustomMarshalerHelper *pSharedCMHelper)
1245 {
1246     CONTRACT (CustomMarshalerInfo*)
1247     {
1248         THROWS;
1249         GC_TRIGGERS;
1250         MODE_COOPERATIVE;
1251         INJECT_FAULT(COMPlusThrowOM());
1252         POSTCONDITION(CheckPointer(RETVAL));
1253     }
1254     CONTRACT_END;
1255     
1256     CustomMarshalerInfo *pCMInfo = NULL;
1257     NewHolder<CustomMarshalerInfo> pNewCMInfo(NULL);
1258     TypeHandle hndCustomMarshalerType;
1259
1260     // Lookup the custom marshaler helper in the hashtable.
1261     if (m_SharedCMHelperToCMInfoMap.GetValue(pSharedCMHelper, (HashDatum*)&pCMInfo))
1262         RETURN pCMInfo;
1263
1264     // Append a NULL terminator to the marshaler type name.
1265     CQuickArray<char> strCMMarshalerTypeName;
1266     DWORD strLen = pSharedCMHelper->GetMarshalerTypeNameByteCount();
1267     strCMMarshalerTypeName.ReSizeThrows(pSharedCMHelper->GetMarshalerTypeNameByteCount() + 1);
1268     memcpy(strCMMarshalerTypeName.Ptr(), pSharedCMHelper->GetMarshalerTypeName(), strLen);
1269     strCMMarshalerTypeName[strLen] = 0;
1270     
1271     // Load the custom marshaler class. 
1272     hndCustomMarshalerType = TypeName::GetTypeUsingCASearchRules(strCMMarshalerTypeName.Ptr(), pSharedCMHelper->GetAssembly());
1273     if (hndCustomMarshalerType.IsGenericTypeDefinition())
1274     {
1275         // Instantiate generic custom marshalers using the instantiation of the type being marshaled.
1276         hndCustomMarshalerType = hndCustomMarshalerType.Instantiate(pSharedCMHelper->GetManagedType().GetInstantiation());
1277     }
1278
1279     // Create the custom marshaler info in the specified heap.
1280     pNewCMInfo = new (m_pHeap) CustomMarshalerInfo(m_pAllocator, 
1281                                                    hndCustomMarshalerType, 
1282                                                    pSharedCMHelper->GetManagedType(), 
1283                                                    pSharedCMHelper->GetCookieString(), 
1284                                                    pSharedCMHelper->GetCookieStringByteCount());
1285
1286     {
1287         CrstHolder lock(m_lock);
1288
1289         // Verify that the custom marshaler info has not already been added by another thread.
1290         if (m_SharedCMHelperToCMInfoMap.GetValue(pSharedCMHelper, (HashDatum*)&pCMInfo))
1291         {
1292             RETURN pCMInfo;
1293         }
1294
1295         // Add the custom marshaler helper to the hash table.
1296         m_SharedCMHelperToCMInfoMap.InsertValue(pSharedCMHelper, pNewCMInfo, FALSE);
1297
1298         // Add the custom marshaler into the linked list.
1299         m_pCMInfoList.InsertHead(pNewCMInfo);
1300
1301         // Release the lock and return the custom marshaler info.
1302     }
1303
1304     pNewCMInfo.SuppressRelease();
1305     RETURN pNewCMInfo;
1306 }
1307 #endif // CROSSGEN_COMPILE
1308
1309 #ifdef FEATURE_COMINTEROP
1310 UriMarshalingInfo *EEMarshalingData::GetUriMarshalingInfo()
1311 {
1312     CONTRACT (UriMarshalingInfo*)
1313     {
1314         THROWS;
1315         GC_TRIGGERS;
1316         MODE_ANY;
1317         INJECT_FAULT(COMPlusThrowOM());
1318         POSTCONDITION(CheckPointer(RETVAL));
1319     }
1320     CONTRACT_END;
1321        
1322     if (m_pUriInfo == NULL)
1323     {
1324         UriMarshalingInfo *pUriInfo = new (m_pHeap) UriMarshalingInfo();
1325
1326         if (InterlockedCompareExchangeT(&m_pUriInfo, pUriInfo, NULL) != NULL)
1327         {
1328             // Another thread beat us to it. Delete on UriMarshalingInfo is an empty operation
1329             // which is OK, since the possible leak is rare, small, and constant. This is the same
1330             // pattern as in code:GetCustomMarshalerInfo.
1331             delete pUriInfo;
1332         }
1333     }
1334
1335     RETURN m_pUriInfo;
1336 }
1337
1338 EventArgsMarshalingInfo *EEMarshalingData::GetEventArgsMarshalingInfo()
1339 {
1340     CONTRACT (EventArgsMarshalingInfo*)
1341     {
1342         THROWS;
1343         GC_TRIGGERS;
1344         MODE_ANY;
1345         INJECT_FAULT(COMPlusThrowOM());
1346         POSTCONDITION(CheckPointer(RETVAL));
1347     }
1348     CONTRACT_END;
1349        
1350     if (m_pEventArgsInfo == NULL)
1351     {
1352         EventArgsMarshalingInfo *pEventArgsInfo = new (m_pHeap) EventArgsMarshalingInfo();
1353
1354         if (InterlockedCompareExchangeT(&m_pEventArgsInfo, pEventArgsInfo, NULL) != NULL)
1355         {
1356             // Another thread beat us to it. Delete on EventArgsMarshalingInfo is an empty operation
1357             // which is OK, since the possible leak is rare, small, and constant. This is the same
1358             // pattern as in code:GetCustomMarshalerInfo.
1359             delete pEventArgsInfo;
1360         }
1361     }
1362
1363     RETURN m_pEventArgsInfo;
1364 }
1365
1366 OleColorMarshalingInfo *EEMarshalingData::GetOleColorMarshalingInfo()
1367 {
1368     CONTRACT (OleColorMarshalingInfo*)
1369     {
1370         THROWS;
1371         GC_TRIGGERS;
1372         MODE_ANY;
1373         INJECT_FAULT(COMPlusThrowOM());
1374         POSTCONDITION(CheckPointer(RETVAL));
1375     }
1376     CONTRACT_END;
1377        
1378     if (m_pOleColorInfo == NULL)
1379     {
1380         OleColorMarshalingInfo *pOleColorInfo = new (m_pHeap) OleColorMarshalingInfo();
1381
1382     if (InterlockedCompareExchangeT(&m_pOleColorInfo, pOleColorInfo, NULL) != NULL)
1383         {
1384             // Another thread beat us to it. Delete on OleColorMarshalingInfo is an empty operation
1385             // which is OK, since the possible leak is rare, small, and constant. This is the same
1386             // pattern as in code:GetCustomMarshalerInfo.
1387             delete pOleColorInfo;
1388         }
1389     }
1390
1391     RETURN m_pOleColorInfo;
1392 }
1393 #endif // FEATURE_COMINTEROP
1394
1395 //==========================================================================
1396 // Constructs MarshalInfo. 
1397 //==========================================================================
1398 #ifdef _PREFAST_
1399 #pragma warning(push)
1400 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
1401 #endif
1402 MarshalInfo::MarshalInfo(Module* pModule,
1403                          SigPointer sig,
1404                          const SigTypeContext *pTypeContext,
1405                          mdToken token,
1406                          MarshalScenario ms,
1407                          CorNativeLinkType nlType,
1408                          CorNativeLinkFlags nlFlags,
1409                          BOOL isParam,
1410                          UINT paramidx,   // parameter # for use in error messages (ignored if not parameter)                         
1411                          UINT numArgs,    // number of arguments
1412                          BOOL BestFit,
1413                          BOOL ThrowOnUnmappableChar,
1414                          BOOL fEmitsIL,
1415                          BOOL onInstanceMethod,
1416                          MethodDesc* pMD,
1417                          BOOL fLoadCustomMarshal
1418 #ifdef _DEBUG
1419                          ,
1420                          LPCUTF8 pDebugName,
1421                          LPCUTF8 pDebugClassName,
1422                          UINT    argidx  // 0 for return value, -1 for field
1423 #endif
1424 )
1425 {
1426     STANDARD_VM_CONTRACT;
1427
1428     HRESULT hr;
1429     NativeTypeParamInfo ParamInfo;
1430
1431     // we expect a 1-based paramidx, but we like to use a 0-based paramidx
1432     m_paramidx                      = paramidx - 1;
1433     
1434     // if no one overwrites this with a better message, we'll still at least say something    
1435     m_resID                         = IDS_EE_BADMARSHAL_GENERIC;
1436
1437     // flag for uninitialized type
1438     m_type                          = MARSHAL_TYPE_UNKNOWN;
1439
1440     CorNativeType nativeType        = NATIVE_TYPE_DEFAULT;
1441     Assembly *pAssembly             = pModule->GetAssembly();
1442     BOOL fNeedsCopyCtor             = FALSE;
1443     m_BestFit                       = BestFit;
1444     m_ThrowOnUnmappableChar         = ThrowOnUnmappableChar;
1445     m_ms                            = ms;
1446     m_fAnsi                         = (ms == MARSHAL_SCENARIO_NDIRECT) && (nlType == nltAnsi);
1447     m_managedArgSize                = 0;
1448     m_nativeArgSize                 = 0;
1449     m_pCMHelper                     = NULL;
1450     m_CMVt                          = VT_EMPTY;
1451     m_args.m_pMarshalInfo           = this;
1452     m_args.m_pMT                    = NULL;
1453     m_pModule                       = pModule;
1454     CorElementType mtype            = ELEMENT_TYPE_END;
1455     CorElementType corElemType      = ELEMENT_TYPE_END;
1456     m_pMT                           = NULL;
1457     m_pMD                           = pMD;
1458
1459 #ifdef FEATURE_COMINTEROP
1460     m_fDispItf                      = FALSE;
1461     m_fInspItf                      = FALSE;
1462     m_fErrorNativeType              = FALSE;
1463     m_hiddenLengthParamIndex        = (UINT16)-1;
1464     m_dwHiddenLengthManagedHomeLocal= 0xFFFFFFFF;
1465     m_dwHiddenLengthNativeHomeLocal = 0xFFFFFFFF;
1466
1467     m_pDefaultItfMT                 = NULL;
1468 #endif // FEATURE_COMINTEROP
1469
1470
1471 #ifdef _DEBUG
1472
1473     CHAR achDbgContext[DEBUG_CONTEXT_STR_LEN] = "";
1474     if (!pDebugName)
1475     {
1476         strncpy_s(achDbgContext, COUNTOF(achDbgContext), "<Unknown>", _TRUNCATE);
1477     }
1478     else
1479     {
1480         strncat_s(achDbgContext, COUNTOF(achDbgContext), pDebugClassName, _TRUNCATE);
1481         strncat_s(achDbgContext, COUNTOF(achDbgContext), NAMESPACE_SEPARATOR_STR, _TRUNCATE);
1482         strncat_s(achDbgContext, COUNTOF(achDbgContext), pDebugName, _TRUNCATE);
1483         strncat_s(achDbgContext, COUNTOF(achDbgContext), " ", _TRUNCATE);
1484         switch (argidx)
1485         {
1486             case (UINT)-1:
1487                 strncat_s(achDbgContext, COUNTOF(achDbgContext), "field", _TRUNCATE);
1488                 break;
1489             case 0:
1490                 strncat_s(achDbgContext, COUNTOF(achDbgContext), "return value", _TRUNCATE);
1491                 break;
1492             default:
1493             {
1494                 char buf[30];
1495                 sprintf_s(buf, COUNTOF(buf), "param #%lu", (ULONG)argidx);
1496                 strncat_s(achDbgContext, COUNTOF(achDbgContext), buf, _TRUNCATE);
1497             }
1498         }
1499     }
1500
1501     m_strDebugMethName = pDebugName;
1502     m_strDebugClassName = pDebugClassName;
1503     m_iArg = argidx;
1504
1505     m_in = m_out = FALSE;
1506     m_byref = TRUE;
1507 #endif
1508
1509
1510
1511     // Retrieve the native type for the current parameter.
1512     if (!ParseNativeTypeInfo(token, pModule->GetMDImport(), &ParamInfo))
1513     {
1514         IfFailGoto(E_FAIL, lFail);
1515     }
1516    
1517     nativeType = ParamInfo.m_NativeType;
1518
1519     corElemType = sig.PeekElemTypeNormalized(pModule, pTypeContext); 
1520     mtype = corElemType;
1521
1522 #ifdef FEATURE_COMINTEROP
1523     if (IsWinRTScenario() && nativeType != NATIVE_TYPE_DEFAULT)
1524     {
1525         // Do not allow any MarshalAs in WinRT scenarios - marshaling is fully described by the parameter type.
1526         m_type = MARSHAL_TYPE_UNKNOWN; 
1527         m_resID = IDS_EE_BADMARSHAL_WINRT_MARSHAL_AS;
1528         IfFailGoto(E_FAIL, lFail);
1529     }
1530 #endif // FEATURE_COMINTEROP
1531
1532     // Make sure SizeParamIndex < numArgs when marshalling native arrays
1533     if (nativeType == NATIVE_TYPE_ARRAY && ParamInfo.m_SizeIsSpecified)
1534     {
1535         if (ParamInfo.m_Multiplier > 0 && ParamInfo.m_CountParamIdx >= numArgs)
1536         {        
1537             // Do not throw exception here. 
1538             // We'll use EmitOrThrowInteropException to throw exception in non-COM interop
1539             // and emit exception throwing code directly in STUB in COM interop
1540             m_type = MARSHAL_TYPE_UNKNOWN; 
1541             m_resID = IDS_EE_SIZECONTROLOUTOFRANGE;
1542             IfFailGoto(E_FAIL, lFail);
1543         }
1544     }
1545
1546     // Parse ET_BYREF signature
1547     if (mtype == ELEMENT_TYPE_BYREF)
1548     {
1549         m_byref = TRUE;
1550         SigPointer sigtmp = sig;
1551         IfFailGoto(sig.GetElemType(NULL), lFail);
1552         mtype = sig.PeekElemTypeNormalized(pModule, pTypeContext); 
1553
1554         // Check for Copy Constructor Modifier - peek closed elem type here to prevent ELEMENT_TYPE_VALUETYPE
1555         // turning into a primitive.
1556         if (sig.PeekElemTypeClosed(pModule, pTypeContext) == ELEMENT_TYPE_VALUETYPE) 
1557         {
1558             // Skip ET_BYREF
1559             IfFailGoto(sigtmp.GetByte(NULL), lFail);
1560             
1561             if (sigtmp.HasCustomModifier(pModule, "Microsoft.VisualC.NeedsCopyConstructorModifier", ELEMENT_TYPE_CMOD_REQD) ||
1562                 sigtmp.HasCustomModifier(pModule, "System.Runtime.CompilerServices.IsCopyConstructed", ELEMENT_TYPE_CMOD_REQD) )
1563             {
1564                 mtype = ELEMENT_TYPE_VALUETYPE;
1565                 fNeedsCopyCtor = TRUE;
1566                 m_byref = FALSE;
1567             }
1568         }
1569     }
1570     else
1571     {
1572         m_byref = FALSE;
1573     }
1574
1575     // Check for valid ET_PTR signature
1576     if (mtype == ELEMENT_TYPE_PTR)
1577     {
1578 #ifdef FEATURE_COMINTEROP
1579         // WinRT does not support ET_PTR
1580         if (IsWinRTScenario())
1581         {
1582             m_type = MARSHAL_TYPE_UNKNOWN; 
1583             m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
1584             IfFailGoto(E_FAIL, lFail);
1585         }
1586 #endif // FEATURE_COMINTEROP
1587
1588         SigPointer sigtmp = sig;
1589         IfFailGoto(sigtmp.GetElemType(NULL), lFail);
1590
1591         // Peek closed elem type here to prevent ELEMENT_TYPE_VALUETYPE turning into a primitive. 
1592         CorElementType mtype2 = sigtmp.PeekElemTypeClosed(pModule, pTypeContext);
1593
1594         if (mtype2 == ELEMENT_TYPE_VALUETYPE) 
1595         {
1596
1597             TypeHandle th = sigtmp.GetTypeHandleThrowing(pModule, pTypeContext);
1598             _ASSERTE(!th.IsNull());
1599
1600             // We want to leave out enums as they surely don't have copy constructors
1601             // plus they are not marked as blittable.
1602             if (!th.IsEnum())
1603             {
1604                 // It should be blittable
1605                 if (!th.IsBlittable())
1606                 {
1607                     m_resID = IDS_EE_BADMARSHAL_PTRNONBLITTABLE;
1608                     IfFailGoto(E_FAIL, lFail);
1609                 }
1610
1611                 // Check for Copy Constructor Modifier
1612                 if (sigtmp.HasCustomModifier(pModule, "Microsoft.VisualC.NeedsCopyConstructorModifier", ELEMENT_TYPE_CMOD_REQD) ||
1613                     sigtmp.HasCustomModifier(pModule, "System.Runtime.CompilerServices.IsCopyConstructed", ELEMENT_TYPE_CMOD_REQD) )
1614                 {
1615                     mtype = mtype2;
1616
1617                     // Keep the sig pointer in sync with mtype (skip ELEMENT_TYPE_PTR) because for the rest
1618                     // of this method we are pretending that the parameter is a value type passed by-value.
1619                     IfFailGoto(sig.GetElemType(NULL), lFail);
1620
1621                     fNeedsCopyCtor = TRUE;
1622                     m_byref = FALSE;
1623                 }
1624             }
1625         }
1626         else
1627         {
1628             if (!(mtype2 != ELEMENT_TYPE_CLASS &&
1629                   mtype2 != ELEMENT_TYPE_STRING &&
1630                   mtype2 != ELEMENT_TYPE_OBJECT &&
1631                   mtype2 != ELEMENT_TYPE_SZARRAY))
1632             {
1633                 m_resID = IDS_EE_BADMARSHAL_PTRSUBTYPE;
1634                 IfFailGoto(E_FAIL, lFail);
1635             }
1636         }
1637     }
1638
1639
1640     // System primitive types (System.Int32, et.al.) will be marshaled as expected
1641     // because the mtype CorElementType is normalized (e.g. ELEMENT_TYPE_I4).
1642 #ifdef _TARGET_X86_
1643     // We however need to detect if such a normalization occurred for non-system
1644     // trivial value types, because we hold CorNativeType belonging to the original
1645     // "un-normalized" signature type. It has to be verified that all the value types
1646     // that have been normalized away have default marshaling or MarshalAs(Struct).
1647     // In addition, the nativeType must be updated with the type of the real primitive inside.
1648     // We don't normalize on return values of member functions since struct return values need to be treated as structures.
1649     if (isParam || !onInstanceMethod)
1650     {
1651         VerifyAndAdjustNormalizedType(pModule, sig, pTypeContext, &mtype, &nativeType);
1652     }
1653     else
1654     {
1655         SigPointer sigtmp = sig;
1656         CorElementType closedElemType = sigtmp.PeekElemTypeClosed(pModule, pTypeContext);
1657         if (closedElemType == ELEMENT_TYPE_VALUETYPE)
1658         {
1659             TypeHandle th = sigtmp.GetTypeHandleThrowing(pModule, pTypeContext); 
1660             // If the return type of an instance method is a value-type we need the actual return type.
1661             // However, if the return type is an enum, we can normalize it.
1662             if (!th.IsEnum())
1663             {
1664                 mtype = closedElemType;
1665             }
1666         }
1667
1668     }
1669 #endif // _TARGET_X86_
1670
1671
1672     if (nativeType == NATIVE_TYPE_CUSTOMMARSHALER)
1673     {
1674         switch (mtype)
1675         {
1676             case ELEMENT_TYPE_VAR:
1677             case ELEMENT_TYPE_CLASS:
1678             case ELEMENT_TYPE_OBJECT:
1679                 m_CMVt = VT_UNKNOWN;
1680                 break;
1681
1682             case ELEMENT_TYPE_STRING:
1683             case ELEMENT_TYPE_SZARRAY:
1684             case ELEMENT_TYPE_ARRAY:
1685                 m_CMVt = VT_I4;
1686                 break;
1687
1688             default:    
1689                 m_resID = IDS_EE_BADMARSHAL_CUSTOMMARSHALER;
1690                 IfFailGoto(E_FAIL, lFail);
1691         }
1692
1693         // Set m_type to MARSHAL_TYPE_UNKNOWN in case SetupCustomMarshalerHelper throws.
1694         m_type = MARSHAL_TYPE_UNKNOWN; 
1695
1696         if (fLoadCustomMarshal)
1697         {
1698             // Set up the custom marshaler info.
1699             TypeHandle hndManagedType = sig.GetTypeHandleThrowing(pModule, pTypeContext);
1700
1701             if (!fEmitsIL)
1702             {
1703                 m_pCMHelper = SetupCustomMarshalerHelper(ParamInfo.m_strCMMarshalerTypeName, 
1704                                                         ParamInfo.m_cCMMarshalerTypeNameBytes,
1705                                                         ParamInfo.m_strCMCookie, 
1706                                                         ParamInfo.m_cCMCookieStrBytes,
1707                                                         pAssembly,
1708                                                         hndManagedType);
1709             }
1710             else
1711             {
1712                 m_pCMHelper = NULL;
1713                 MethodDesc* pMDforModule = pMD;
1714                 if (pMD->IsILStub())
1715                 {
1716                     pMDforModule = pMD->AsDynamicMethodDesc()->GetILStubResolver()->GetStubTargetMethodDesc();
1717                 }
1718                 m_args.rcm.m_pMD = pMDforModule;
1719                 m_args.rcm.m_paramToken = token;
1720                 m_args.rcm.m_hndManagedType = hndManagedType.AsPtr();
1721                 CONSISTENCY_CHECK(pModule == pMDforModule->GetModule());
1722             }
1723         }
1724
1725         // Specify which custom marshaler to use.
1726         m_type = MARSHAL_TYPE_REFERENCECUSTOMMARSHALER;
1727
1728         goto lExit;
1729     }
1730    
1731     switch (mtype)
1732     {
1733         case ELEMENT_TYPE_BOOLEAN:
1734             switch (nativeType)
1735             {
1736                 case NATIVE_TYPE_BOOLEAN:
1737                     m_type = MARSHAL_TYPE_WINBOOL;
1738                     break;
1739
1740 #ifdef FEATURE_COMINTEROP
1741                 case NATIVE_TYPE_VARIANTBOOL:
1742                     m_type = MARSHAL_TYPE_VTBOOL;
1743                     break;
1744 #endif // FEATURE_COMINTEROP
1745
1746                 case NATIVE_TYPE_U1:
1747                 case NATIVE_TYPE_I1:
1748                     m_type = MARSHAL_TYPE_CBOOL;
1749                     break;
1750
1751                 case NATIVE_TYPE_DEFAULT:
1752 #ifdef FEATURE_COMINTEROP
1753                     if (m_ms == MARSHAL_SCENARIO_COMINTEROP)
1754                     {
1755                         // 2-byte COM VARIANT_BOOL
1756                         m_type = MARSHAL_TYPE_VTBOOL;
1757                     }
1758                     else if (m_ms == MARSHAL_SCENARIO_WINRT)
1759                     {
1760                         // 1-byte WinRT bool
1761                         m_type = MARSHAL_TYPE_CBOOL;
1762                     }
1763                     else
1764 #endif // FEATURE_COMINTEROP
1765                     {
1766                         // 4-byte Windows BOOL
1767                         _ASSERTE(m_ms == MARSHAL_SCENARIO_NDIRECT);
1768                         m_type = MARSHAL_TYPE_WINBOOL;
1769                     }
1770                     break;
1771
1772                 default:
1773                     m_resID = IDS_EE_BADMARSHAL_BOOLEAN;
1774                     IfFailGoto(E_FAIL, lFail);
1775             }
1776             break;
1777
1778         case ELEMENT_TYPE_CHAR:
1779             switch (nativeType)
1780             {
1781                 case NATIVE_TYPE_I1: //fallthru
1782                 case NATIVE_TYPE_U1:
1783                     m_type = MARSHAL_TYPE_ANSICHAR;
1784                     break;
1785
1786                 case NATIVE_TYPE_I2: //fallthru
1787                 case NATIVE_TYPE_U2:
1788                     m_type = MARSHAL_TYPE_GENERIC_U2;
1789                     break;
1790
1791                 case NATIVE_TYPE_DEFAULT:
1792                     m_type = ( (m_ms == MARSHAL_SCENARIO_NDIRECT && m_fAnsi) ? MARSHAL_TYPE_ANSICHAR : MARSHAL_TYPE_GENERIC_U2 );
1793                     break;
1794
1795                 default:
1796                     m_resID = IDS_EE_BADMARSHAL_CHAR;
1797                     IfFailGoto(E_FAIL, lFail);
1798
1799             }
1800             break;
1801
1802         case ELEMENT_TYPE_I1:
1803             if (!(nativeType == NATIVE_TYPE_I1 || nativeType == NATIVE_TYPE_U1 || nativeType == NATIVE_TYPE_DEFAULT))
1804             {
1805                 m_resID = IDS_EE_BADMARSHAL_I1;
1806                 IfFailGoto(E_FAIL, lFail);
1807             }
1808             m_type = MARSHAL_TYPE_GENERIC_1;
1809             break;
1810
1811         case ELEMENT_TYPE_U1:
1812             if (!(nativeType == NATIVE_TYPE_U1 || nativeType == NATIVE_TYPE_I1 || nativeType == NATIVE_TYPE_DEFAULT))
1813             {
1814                 m_resID = IDS_EE_BADMARSHAL_I1;
1815                 IfFailGoto(E_FAIL, lFail);
1816             }
1817             m_type = MARSHAL_TYPE_GENERIC_U1;
1818             break;
1819
1820         case ELEMENT_TYPE_I2:
1821             if (!(nativeType == NATIVE_TYPE_I2 || nativeType == NATIVE_TYPE_U2 || nativeType == NATIVE_TYPE_DEFAULT))
1822             {
1823                 m_resID = IDS_EE_BADMARSHAL_I2;
1824                 IfFailGoto(E_FAIL, lFail);
1825             }
1826             m_type = MARSHAL_TYPE_GENERIC_2;
1827             break;
1828
1829         case ELEMENT_TYPE_U2:
1830             if (!(nativeType == NATIVE_TYPE_U2 || nativeType == NATIVE_TYPE_I2 || nativeType == NATIVE_TYPE_DEFAULT))
1831             {
1832                 m_resID = IDS_EE_BADMARSHAL_I2;
1833                 IfFailGoto(E_FAIL, lFail);
1834             }
1835             m_type = MARSHAL_TYPE_GENERIC_U2;
1836             break;
1837
1838         case ELEMENT_TYPE_I4:
1839             switch (nativeType)
1840             {
1841                 case NATIVE_TYPE_I4:
1842                 case NATIVE_TYPE_U4:
1843                 case NATIVE_TYPE_DEFAULT:
1844                     break;
1845
1846 #ifdef FEATURE_COMINTEROP
1847                 case NATIVE_TYPE_ERROR:
1848                     m_fErrorNativeType = TRUE;
1849                     break;
1850 #endif // FEATURE_COMINTEROP
1851
1852                 default:
1853                 m_resID = IDS_EE_BADMARSHAL_I4;
1854                 IfFailGoto(E_FAIL, lFail);
1855             }
1856             m_type = MARSHAL_TYPE_GENERIC_4;
1857             break;
1858
1859         case ELEMENT_TYPE_U4:
1860             switch (nativeType)
1861             {
1862                 case NATIVE_TYPE_I4:
1863                 case NATIVE_TYPE_U4:
1864                 case NATIVE_TYPE_DEFAULT:
1865                     break;
1866
1867 #ifdef FEATURE_COMINTEROP
1868                 case NATIVE_TYPE_ERROR:
1869                     m_fErrorNativeType = TRUE;
1870                     break;
1871 #endif // FEATURE_COMINTEROP
1872
1873                 default:
1874                 m_resID = IDS_EE_BADMARSHAL_I4;
1875                 IfFailGoto(E_FAIL, lFail);
1876             }
1877             m_type = MARSHAL_TYPE_GENERIC_4;
1878             break;
1879
1880         case ELEMENT_TYPE_I8:
1881             if (!(nativeType == NATIVE_TYPE_I8 || nativeType == NATIVE_TYPE_U8 || nativeType == NATIVE_TYPE_DEFAULT))
1882             {
1883                 m_resID = IDS_EE_BADMARSHAL_I8;
1884                 IfFailGoto(E_FAIL, lFail);
1885             }
1886             m_type = MARSHAL_TYPE_GENERIC_8;
1887             break;
1888
1889         case ELEMENT_TYPE_U8:
1890             if (!(nativeType == NATIVE_TYPE_U8 || nativeType == NATIVE_TYPE_I8 || nativeType == NATIVE_TYPE_DEFAULT))
1891             {
1892                 m_resID = IDS_EE_BADMARSHAL_I8;
1893                 IfFailGoto(E_FAIL, lFail);
1894             }
1895             m_type = MARSHAL_TYPE_GENERIC_8;
1896             break;
1897
1898         case ELEMENT_TYPE_I:
1899             // Technically the "native int" and "native uint" types aren't supported in the WinRT scenario,
1900             // but we need to not block ourselves from using them to enable accurate managed->native marshalling of
1901             // projected types such as NotifyCollectionChangedEventArgs and NotifyPropertyChangedEventArgs.
1902
1903             if (!(nativeType == NATIVE_TYPE_INT || nativeType == NATIVE_TYPE_UINT || nativeType == NATIVE_TYPE_DEFAULT))
1904             {
1905                 m_resID = IDS_EE_BADMARSHAL_I;
1906                 IfFailGoto(E_FAIL, lFail);
1907             }
1908             m_type = (sizeof(LPVOID) == 4 ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8);
1909             break;
1910
1911         case ELEMENT_TYPE_U:
1912
1913             if (!(nativeType == NATIVE_TYPE_UINT || nativeType == NATIVE_TYPE_INT || nativeType == NATIVE_TYPE_DEFAULT))
1914             {
1915                 m_resID = IDS_EE_BADMARSHAL_I;
1916                 IfFailGoto(E_FAIL, lFail);
1917             }
1918             m_type = (sizeof(LPVOID) == 4 ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8);
1919             break;
1920
1921
1922         case ELEMENT_TYPE_R4:
1923             if (!(nativeType == NATIVE_TYPE_R4 || nativeType == NATIVE_TYPE_DEFAULT))
1924             {
1925                 m_resID = IDS_EE_BADMARSHAL_R4;
1926                 IfFailGoto(E_FAIL, lFail);
1927             }
1928             m_type = MARSHAL_TYPE_FLOAT;
1929             break;
1930
1931         case ELEMENT_TYPE_R8:
1932             if (!(nativeType == NATIVE_TYPE_R8 || nativeType == NATIVE_TYPE_DEFAULT))
1933             {
1934                 m_resID = IDS_EE_BADMARSHAL_R8;
1935                 IfFailGoto(E_FAIL, lFail);
1936             }
1937             m_type = MARSHAL_TYPE_DOUBLE;
1938             break;
1939
1940         case ELEMENT_TYPE_PTR:
1941 #ifdef FEATURE_COMINTEROP
1942             _ASSERTE(!IsWinRTScenario()); // we checked for this earlier
1943 #endif // FEATURE_COMINTEROP
1944
1945             if (nativeType != NATIVE_TYPE_DEFAULT)
1946             {
1947                 m_resID = IDS_EE_BADMARSHAL_PTR;
1948                 IfFailGoto(E_FAIL, lFail);
1949             }
1950             m_type = ( (sizeof(void*)==4) ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8 );
1951             break;
1952
1953         case ELEMENT_TYPE_FNPTR:
1954 #ifdef FEATURE_COMINTEROP
1955             if (IsWinRTScenario())
1956             {
1957                 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
1958                 IfFailGoto(E_FAIL, lFail);
1959             }
1960 #endif // FEATURE_COMINTEROP
1961
1962             if (!(nativeType == NATIVE_TYPE_FUNC || nativeType == NATIVE_TYPE_DEFAULT))
1963             {
1964                 m_resID = IDS_EE_BADMARSHAL_FNPTR;
1965                 IfFailGoto(E_FAIL, lFail);
1966             }
1967             m_type = ( (sizeof(void*)==4) ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8 );
1968             break;
1969
1970         case ELEMENT_TYPE_OBJECT:
1971         case ELEMENT_TYPE_STRING:
1972         case ELEMENT_TYPE_CLASS:
1973         case ELEMENT_TYPE_VAR:
1974         {                
1975             TypeHandle sigTH = sig.GetTypeHandleThrowing(pModule, pTypeContext);
1976
1977             // Disallow marshaling generic types except for WinRT interfaces.
1978             if (sigTH.HasInstantiation())
1979             {
1980 #ifdef FEATURE_COMINTEROP
1981                 if (!sigTH.SupportsGenericInterop(TypeHandle::Interop_NativeToManaged))
1982 #endif // FEATURE_COMINTEROP
1983                 {
1984                     m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
1985                     IfFailGoto(E_FAIL, lFail);
1986                 }
1987             }
1988             
1989             m_pMT = sigTH.GetMethodTable();
1990             if (m_pMT == NULL)
1991                 IfFailGoto(COR_E_TYPELOAD, lFail);
1992
1993 #ifdef FEATURE_COMINTEROP
1994             MethodTable* pDefaultMT = NULL;
1995
1996             // Look for marshaling of WinRT runtime classes
1997             if ((m_pMT->IsProjectedFromWinRT() || m_pMT->IsExportedToWinRT()) && !m_pMT->HasExplicitGuid())
1998             {
1999                 // The type loader guarantees that there are no WinRT interfaces without explicit GUID
2000                 _ASSERTE(!m_pMT->IsInterface());
2001
2002                 // Make sure that this is really a legal runtime class and not a custom attribute or delegate
2003                 if (!m_pMT->IsLegalNonArrayWinRTType() || m_pMT->IsDelegate())
2004                 {
2005                     m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
2006                     IfFailGoto(E_FAIL, lFail);
2007                 }
2008
2009                 // This class must have a default interface that describes how it is marshaled
2010                 pDefaultMT = m_pMT->GetDefaultWinRTInterface();
2011                 if (pDefaultMT == NULL)
2012                 {
2013                     m_resID = IDS_EE_BADMARSHAL_WINRT_MISSING_GUID;
2014                     IfFailGoto(E_FAIL, lFail);
2015                 }
2016             }
2017
2018             if (nativeType == NATIVE_TYPE_INTF)
2019             {
2020                 // whatever...
2021                 if (sig.IsStringType(pModule, pTypeContext)) 
2022                 {
2023                     m_resID = IDS_EE_BADMARSHALPARAM_STRING;
2024                     IfFailGoto(E_FAIL, lFail);
2025                 }
2026
2027                 if (COMDelegate::IsDelegate(m_pMT))
2028                 {
2029                     if (m_ms == MARSHAL_SCENARIO_WINRT)
2030                     {
2031                         // In WinRT scenarios delegates must be WinRT delegates
2032                         if (!m_pMT->IsProjectedFromWinRT() && !WinRTTypeNameConverter::IsRedirectedType(m_pMT))
2033                         {
2034                             m_resID = IDS_EE_BADMARSHAL_WINRT_DELEGATE;
2035                             IfFailGoto(E_FAIL, lFail);
2036                         }
2037                     }
2038                     else
2039                     {
2040                         // UnmanagedType.Interface for delegates used to mean the .NET Framework _Delegate interface.
2041                         // We don't support that interface in .NET Core, so we disallow marshalling as it here.
2042                         // The user can specify UnmanagedType.IDispatch and use the delegate through the IDispatch interface
2043                         // if they need an interface pointer.
2044                         m_resID = IDS_EE_BADMARSHAL_DELEGATE_TLB_INTERFACE;
2045                         IfFailGoto(E_FAIL, lFail);
2046                     }
2047                 }
2048                 m_type = MARSHAL_TYPE_INTERFACE;
2049             }
2050             else if (pDefaultMT != NULL && nativeType == NATIVE_TYPE_DEFAULT)
2051             {
2052                 // Pretend this is really marshaling as the default interface type
2053
2054                 // Validate it's a WinRT interface with GUID
2055                 if (!pDefaultMT->IsInterface() ||
2056                     (!pDefaultMT->IsProjectedFromWinRT() && !pDefaultMT->IsExportedToWinRT()) ||
2057                     !pDefaultMT->HasExplicitGuid())
2058                 {
2059                     // This might also be a redirected interface - which is also allowed
2060                     if (!pDefaultMT->IsWinRTRedirectedInterface(TypeHandle::Interop_NativeToManaged))
2061                     {
2062                         m_resID = IDS_EE_BADMARSHAL_DEFAULTIFACE_NOT_WINRT_IFACE;
2063                         IfFailGoto(E_FAIL, lFail);
2064                     }
2065                 }
2066
2067                 // Validate that it's one of the component interfaces of the class in the signature
2068                 if (!m_pMT->ImplementsEquivalentInterface(pDefaultMT))
2069                 {
2070                     m_resID = IDS_EE_BADMARSHAL_DEFAULTIFACE_NOT_SUBTYPE;
2071                     IfFailGoto(E_FAIL, lFail);
2072                 }
2073
2074                 // Make sure it's not an unexpected generic case (not clear we can actually get here in practice due
2075                 // to the above Implements check)
2076                 if (pDefaultMT->HasInstantiation() && !pDefaultMT->SupportsGenericInterop(TypeHandle::Interop_NativeToManaged))
2077                 {
2078                     m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
2079                     IfFailGoto(E_FAIL, lFail);
2080                 }
2081
2082                 // Store the marshal data just as if we were marshaling as this default interface type
2083                 m_type = MARSHAL_TYPE_INTERFACE;
2084                 m_pDefaultItfMT = pDefaultMT;
2085             }
2086             else
2087 #endif // FEATURE_COMINTEROP
2088             {
2089                 bool builder = false;
2090                 if (sig.IsStringTypeThrowing(pModule, pTypeContext) 
2091                     || ((builder = true), 0)
2092                     || sig.IsClassThrowing(pModule, g_StringBufferClassName, pTypeContext)
2093                     )
2094                 {
2095                     switch ( nativeType )
2096                     {
2097                         case NATIVE_TYPE_LPWSTR:
2098                             m_type = builder ? MARSHAL_TYPE_LPWSTR_BUFFER : MARSHAL_TYPE_LPWSTR;
2099                             break;
2100         
2101                         case NATIVE_TYPE_LPSTR:
2102                             m_type = builder ? MARSHAL_TYPE_LPSTR_BUFFER : MARSHAL_TYPE_LPSTR;
2103                             break;
2104
2105                         case NATIVE_TYPE_LPUTF8STR:
2106                             m_type = builder ? MARSHAL_TYPE_UTF8_BUFFER : MARSHAL_TYPE_LPUTF8STR;
2107                             break;
2108     
2109                         case NATIVE_TYPE_LPTSTR:
2110                         {
2111 #ifdef FEATURE_COMINTEROP
2112                             if (m_ms != MARSHAL_SCENARIO_NDIRECT)
2113                             {
2114                                 _ASSERTE(m_ms == MARSHAL_SCENARIO_COMINTEROP);
2115                                 // We disallow NATIVE_TYPE_LPTSTR for COM. 
2116                                 IfFailGoto(E_FAIL, lFail);
2117                             }
2118 #endif // FEATURE_COMINTEROP
2119                             // We no longer support Win9x so LPTSTR always maps to a Unicode string.
2120                             m_type = builder ? MARSHAL_TYPE_LPWSTR_BUFFER : MARSHAL_TYPE_LPWSTR;
2121                             break;
2122                         }
2123
2124                         case NATIVE_TYPE_BSTR:
2125                             if (builder)
2126                             {
2127                                 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2128                                 IfFailGoto(E_FAIL, lFail);
2129                             }
2130                             m_type = MARSHAL_TYPE_BSTR;
2131                             break;
2132
2133                         case NATIVE_TYPE_ANSIBSTR:
2134                             if (builder)
2135                             {
2136                                 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2137                                 IfFailGoto(E_FAIL, lFail);
2138                             }
2139                             m_type = MARSHAL_TYPE_ANSIBSTR;
2140                             break;
2141                             
2142                         case NATIVE_TYPE_TBSTR:
2143                         {
2144                             if (builder)
2145                             {
2146                                 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2147                                 IfFailGoto(E_FAIL, lFail);
2148                             }
2149                             
2150                             // We no longer support Win9x so TBSTR always maps to a normal (unicode) BSTR.
2151                             m_type = MARSHAL_TYPE_BSTR;
2152                             break;
2153                         }
2154
2155 #ifdef FEATURE_COMINTEROP
2156                         case NATIVE_TYPE_BYVALSTR:
2157                         {
2158                             if (builder)
2159                             {
2160                                 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2161                                 IfFailGoto(E_FAIL, lFail);
2162                             }
2163                             m_type = m_fAnsi ? MARSHAL_TYPE_VBBYVALSTR : MARSHAL_TYPE_VBBYVALSTRW;
2164                             break;
2165                         }
2166
2167                         case NATIVE_TYPE_HSTRING:
2168                         {
2169                             if (builder)
2170                             {
2171                                 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2172                                 IfFailGoto(E_FAIL, lFail);
2173                             }
2174
2175                             m_type = MARSHAL_TYPE_HSTRING;
2176                             break;
2177                         }
2178 #endif // FEATURE_COMINTEROP
2179     
2180                         case NATIVE_TYPE_DEFAULT:
2181                         {
2182 #ifdef FEATURE_COMINTEROP
2183                             if (m_ms == MARSHAL_SCENARIO_WINRT)
2184                             {
2185                                 if (builder)
2186                                 {
2187                                     m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2188                                     IfFailGoto(E_FAIL, lFail);
2189                                 }
2190
2191                                 m_type = MARSHAL_TYPE_HSTRING;
2192                             }
2193                             else if (m_ms != MARSHAL_SCENARIO_NDIRECT)
2194                             {
2195                                 _ASSERTE(m_ms == MARSHAL_SCENARIO_COMINTEROP);
2196                                 m_type = builder ? MARSHAL_TYPE_LPWSTR_BUFFER : MARSHAL_TYPE_BSTR;
2197                             }
2198                             else
2199 #endif // FEATURE_COMINTEROP
2200                             if (m_fAnsi)
2201                             {
2202                                 m_type = builder ? MARSHAL_TYPE_LPSTR_BUFFER : MARSHAL_TYPE_LPSTR;
2203                             }
2204                             else
2205                             {
2206                                 m_type = builder ? MARSHAL_TYPE_LPWSTR_BUFFER : MARSHAL_TYPE_LPWSTR;
2207                             }
2208                             break;
2209                         }
2210     
2211                         default:
2212                             m_resID = builder ? IDS_EE_BADMARSHALPARAM_STRINGBUILDER : IDS_EE_BADMARSHALPARAM_STRING;
2213                             IfFailGoto(E_FAIL, lFail);
2214                             break;
2215                     }
2216                 }
2217 #ifdef FEATURE_COMINTEROP
2218                 else if (sig.IsClassThrowing(pModule, g_CollectionsEnumeratorClassName, pTypeContext) && 
2219                          nativeType == NATIVE_TYPE_DEFAULT)
2220                 {
2221                     m_CMVt = VT_UNKNOWN;
2222                     m_type = MARSHAL_TYPE_REFERENCECUSTOMMARSHALER;
2223
2224                     if (fLoadCustomMarshal)
2225                     {
2226                         if (!fEmitsIL)
2227                         {
2228                             m_pCMHelper = SetupCustomMarshalerHelper(ENUMERATOR_TO_ENUM_VARIANT_CM_NAME, 
2229                                                                      ENUMERATOR_TO_ENUM_VARIANT_CM_NAME_LEN,
2230                                                                      ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE, 
2231                                                                      ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE_LEN, 
2232                                                                      pAssembly, sigTH);
2233                         }
2234                         else
2235                         {
2236                             m_pCMHelper = NULL;
2237                             MethodDesc* pMDforModule = pMD;
2238                             if (pMD->IsILStub())
2239                             {
2240                                 pMDforModule = pMD->AsDynamicMethodDesc()->GetILStubResolver()->GetStubTargetMethodDesc();
2241                             }
2242                             m_args.rcm.m_pMD = pMDforModule;
2243                             m_args.rcm.m_paramToken = token;
2244                             m_args.rcm.m_hndManagedType = sigTH.AsPtr();
2245                             CONSISTENCY_CHECK(pModule == pMDforModule->GetModule());
2246                         }
2247                     }
2248                 }
2249 #endif // FEATURE_COMINTEROP
2250                 else if (sigTH.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__SAFE_HANDLE))))
2251                 {
2252                     if (nativeType != NATIVE_TYPE_DEFAULT)
2253                     {
2254                         m_resID = IDS_EE_BADMARSHAL_SAFEHANDLE;
2255                         IfFailGoto(E_FAIL, lFail);
2256                     }
2257                     m_args.m_pMT = m_pMT;
2258                     m_type = MARSHAL_TYPE_SAFEHANDLE;
2259                 }
2260                 else if (sigTH.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__CRITICAL_HANDLE))))
2261                 {
2262                     if (nativeType != NATIVE_TYPE_DEFAULT)
2263                     {
2264                         m_resID = IDS_EE_BADMARSHAL_CRITICALHANDLE;
2265                         IfFailGoto(E_FAIL, lFail);
2266                     }
2267                     m_args.m_pMT = m_pMT;
2268                     m_type = MARSHAL_TYPE_CRITICALHANDLE;
2269                 }
2270                 else if (sig.IsClassThrowing(pModule, g_ReflectionMethodInterfaceName, pTypeContext))
2271                 {
2272                     if (nativeType != NATIVE_TYPE_DEFAULT)
2273                     {
2274                         IfFailGoto(E_FAIL, lFail);
2275                     }
2276
2277                     m_type = MARSHAL_TYPE_RUNTIMEMETHODINFO;
2278                 }
2279 #ifdef FEATURE_COMINTEROP
2280                 else if (m_pMT->IsInterface())
2281                 {
2282                     if (!(nativeType == NATIVE_TYPE_DEFAULT ||
2283                           nativeType == NATIVE_TYPE_INTF))
2284                     {
2285                         m_resID = IDS_EE_BADMARSHAL_INTERFACE;
2286                         IfFailGoto(E_FAIL, lFail);
2287                     }
2288                     m_type = MARSHAL_TYPE_INTERFACE;
2289
2290                     if (m_ms == MARSHAL_SCENARIO_WINRT)
2291                     {
2292                         // all interfaces marshaled in WinRT scenarios are IInspectable-based
2293                         m_fInspItf = TRUE;
2294                     }
2295                 }
2296                 // Check for Windows.Foundation.HResult <-> Exception
2297                 else if (m_ms == MARSHAL_SCENARIO_WINRT && MscorlibBinder::IsClass(m_pMT, CLASS__EXCEPTION))
2298                 {
2299                     m_args.m_pMT = m_pMT;
2300                     m_type = MARSHAL_TYPE_EXCEPTION;
2301                 }
2302 #endif // FEATURE_COMINTEROP
2303                 else if (COMDelegate::IsDelegate(m_pMT))
2304                 {
2305                     m_args.m_pMT = m_pMT;
2306 #ifdef FEATURE_COMINTEROP
2307                     if (m_ms == MARSHAL_SCENARIO_WINRT)
2308                     {
2309                         // Delegates must be imported from WinRT and marshaled as Interface
2310                         if (!m_pMT->IsProjectedFromWinRT() && !WinRTTypeNameConverter::IsRedirectedType(m_pMT))
2311                         {
2312                             m_resID = IDS_EE_BADMARSHAL_WINRT_DELEGATE;
2313                             IfFailGoto(E_FAIL, lFail);
2314                         }
2315                     }
2316 #endif // FEATURE_COMINTEROP
2317
2318                     switch (nativeType)
2319                     {
2320                         case NATIVE_TYPE_FUNC:
2321                             m_type = MARSHAL_TYPE_DELEGATE;
2322                             break;
2323
2324                         case NATIVE_TYPE_DEFAULT:
2325 #ifdef FEATURE_COMINTEROP
2326                             if (m_ms == MARSHAL_SCENARIO_WINRT)
2327                             {
2328                                 m_type = MARSHAL_TYPE_INTERFACE;
2329                             }
2330                             else if (m_ms == MARSHAL_SCENARIO_COMINTEROP)
2331                             {
2332                                 // Default for COM marshalling for delegates used to mean the .NET Framework _Delegate interface.
2333                                 // We don't support that interface in .NET Core, so we disallow marshalling as it here.
2334                                 // The user can specify UnmanagedType.IDispatch and use the delegate through the IDispatch interface
2335                                 // if they need an interface pointer.
2336                                 m_resID = IDS_EE_BADMARSHAL_DELEGATE_TLB_INTERFACE;
2337                                 IfFailGoto(E_FAIL, lFail);
2338                             }
2339                             else
2340 #endif // FEATURE_COMINTEROP
2341                                 m_type = MARSHAL_TYPE_DELEGATE;
2342
2343                             break;
2344 #ifdef FEATURE_COMINTEROP
2345                         case NATIVE_TYPE_IDISPATCH:
2346                             m_type = MARSHAL_TYPE_INTERFACE;
2347                             break;
2348 #endif
2349                         default:
2350                         m_resID = IDS_EE_BADMARSHAL_DELEGATE;
2351                         IfFailGoto(E_FAIL, lFail);
2352                             break;
2353                     }
2354                 }
2355                 else if (m_pMT->IsBlittable())
2356                 {
2357                     if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_LPSTRUCT))
2358                     {
2359                         m_resID = IDS_EE_BADMARSHAL_CLASS;
2360                         IfFailGoto(E_FAIL, lFail);
2361                     }
2362                     m_type = MARSHAL_TYPE_BLITTABLEPTR;
2363                     m_args.m_pMT = m_pMT;
2364                 }
2365                 else if (m_pMT->HasLayout())
2366                 {
2367                     if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_LPSTRUCT))
2368                     {
2369                         m_resID = IDS_EE_BADMARSHAL_CLASS;
2370                         IfFailGoto(E_FAIL, lFail);
2371                     }
2372                     m_type = MARSHAL_TYPE_LAYOUTCLASSPTR;
2373                     m_args.m_pMT = m_pMT;
2374                 }    
2375                 else if (sig.IsClassThrowing(pModule, g_ReflectionModuleName, pTypeContext))
2376                 {
2377                     if (nativeType != NATIVE_TYPE_DEFAULT)
2378                     {
2379                         IfFailGoto(E_FAIL, lFail);
2380                     }
2381
2382                     m_type = MARSHAL_TYPE_RUNTIMEMODULE;
2383                 }
2384                 else if (sig.IsClassThrowing(pModule, g_ReflectionAssemblyName, pTypeContext))
2385                 {
2386                     if (nativeType != NATIVE_TYPE_DEFAULT)
2387                     {
2388                         IfFailGoto(E_FAIL, lFail);
2389                     }
2390
2391                     m_type = MARSHAL_TYPE_RUNTIMEASSEMBLY;
2392                 }
2393 #ifdef FEATURE_COMINTEROP
2394                 else if (m_ms == MARSHAL_SCENARIO_WINRT && sig.IsClassThrowing(pModule, g_SystemUriClassName, pTypeContext))
2395                 {
2396                     m_type = MARSHAL_TYPE_URI;
2397                 }
2398                 else if (m_ms == MARSHAL_SCENARIO_WINRT && sig.IsClassThrowing(pModule, g_NotifyCollectionChangedEventArgsName, pTypeContext))
2399                 {
2400                     m_type = MARSHAL_TYPE_NCCEVENTARGS;
2401                 }
2402                 else if (m_ms == MARSHAL_SCENARIO_WINRT && sig.IsClassThrowing(pModule, g_PropertyChangedEventArgsName, pTypeContext))
2403                 {
2404                     m_type = MARSHAL_TYPE_PCEVENTARGS;
2405                 }
2406 #endif // FEATURE_COMINTEROP
2407                 else if (m_pMT->IsObjectClass())
2408                 {
2409                     switch(nativeType)
2410                     {
2411 #ifdef FEATURE_COMINTEROP
2412                         case NATIVE_TYPE_DEFAULT:
2413                             if (ms == MARSHAL_SCENARIO_WINRT)
2414                             {
2415                                 m_fInspItf = TRUE;
2416                                 m_type = MARSHAL_TYPE_INTERFACE;
2417                                 break;
2418                             }
2419                             // fall through
2420                         case NATIVE_TYPE_STRUCT:
2421                             m_type = MARSHAL_TYPE_OBJECT;
2422                             break;
2423
2424                         case NATIVE_TYPE_INTF:
2425                         case NATIVE_TYPE_IUNKNOWN:
2426                             m_type = MARSHAL_TYPE_INTERFACE;
2427                             break;
2428
2429                         case NATIVE_TYPE_IDISPATCH:
2430                             m_fDispItf = TRUE;
2431                             m_type = MARSHAL_TYPE_INTERFACE;
2432                             break;
2433
2434                         case NATIVE_TYPE_IINSPECTABLE:
2435                             m_fInspItf = TRUE;
2436                             m_type = MARSHAL_TYPE_INTERFACE;
2437                             break;
2438 #else
2439                         case NATIVE_TYPE_DEFAULT:
2440                         case NATIVE_TYPE_STRUCT:
2441                             m_resID = IDS_EE_OBJECT_TO_VARIANT_NOT_SUPPORTED;
2442                             IfFailGoto(E_FAIL, lFail);
2443
2444                         case NATIVE_TYPE_INTF:
2445                         case NATIVE_TYPE_IUNKNOWN:
2446                         case NATIVE_TYPE_IDISPATCH:
2447                             m_resID = IDS_EE_OBJECT_TO_ITF_NOT_SUPPORTED;
2448                             IfFailGoto(E_FAIL, lFail);
2449 #endif // FEATURE_COMINTEROP
2450
2451                         case NATIVE_TYPE_ASANY:
2452                             m_type = m_fAnsi ? MARSHAL_TYPE_ASANYA : MARSHAL_TYPE_ASANYW;
2453                             break;
2454
2455                         default:
2456                             m_resID = IDS_EE_BADMARSHAL_OBJECT;
2457                             IfFailGoto(E_FAIL, lFail);
2458                     }
2459                 }
2460                
2461 #ifdef FEATURE_COMINTEROP
2462                 else if (sig.IsClassThrowing(pModule, g_ArrayClassName, pTypeContext))
2463                 {            
2464                     if (IsWinRTScenario())
2465                     {
2466                         m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
2467                         IfFailGoto(E_FAIL, lFail);
2468                     }
2469
2470                     switch(nativeType)
2471                     {
2472                         case NATIVE_TYPE_DEFAULT:
2473                         case NATIVE_TYPE_INTF:
2474                             m_type = MARSHAL_TYPE_INTERFACE;
2475                             break;
2476
2477                         case NATIVE_TYPE_SAFEARRAY:
2478                         {
2479                             TypeHandle thElement = TypeHandle(g_pObjectClass);
2480                             
2481                             if (ParamInfo.m_SafeArrayElementVT != VT_EMPTY)
2482                             {
2483                                 if (ParamInfo.m_cSafeArrayUserDefTypeNameBytes > 0)
2484                                 {
2485                                     // Load the type. Use an SString for the string since we need to NULL terminate the string
2486                                     // that comes from the metadata.
2487                                     StackScratchBuffer utf8Name;
2488                                     SString safeArrayUserDefTypeName(SString::Utf8, ParamInfo.m_strSafeArrayUserDefTypeName, ParamInfo.m_cSafeArrayUserDefTypeNameBytes);
2489                                     thElement = TypeName::GetTypeUsingCASearchRules(safeArrayUserDefTypeName.GetUTF8(utf8Name), pAssembly);
2490                                 }
2491                             }
2492                             else
2493                             {
2494                                 // Compat: If no safe array VT was specified, default to VT_VARIANT.
2495                                 ParamInfo.m_SafeArrayElementVT = VT_VARIANT;
2496                             }
2497                             
2498                             IfFailGoto(HandleArrayElemType(&ParamInfo, thElement, -1, FALSE, isParam, pAssembly), lFail);
2499                             break;
2500                         }
2501
2502                         default:
2503                             m_resID = IDS_EE_BADMARSHAL_SYSARRAY;
2504                             IfFailGoto(E_FAIL, lFail);
2505  
2506                     }
2507                 }
2508
2509                 else if (m_pMT->IsArray())
2510                 {                   
2511                     _ASSERTE(!"This invalid signature should never be hit!");
2512                     IfFailGoto(E_FAIL, lFail);
2513                 }
2514                 else if ((m_ms == MARSHAL_SCENARIO_WINRT) && sig.IsClassThrowing(pModule, g_TypeClassName, pTypeContext))
2515                 {
2516                     m_type = MARSHAL_TYPE_SYSTEMTYPE;
2517                 }
2518 #endif // FEATURE_COMINTEROP
2519                 else if (!m_pMT->IsValueType())
2520                 {
2521 #ifdef FEATURE_COMINTEROP
2522                     if (IsWinRTScenario() && !m_pMT->IsLegalNonArrayWinRTType())
2523                     {
2524                         m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
2525                         IfFailGoto(E_FAIL, lFail);
2526                     }
2527 #endif // FEATURE_COMINTEROP
2528
2529                     if (!(nativeType == NATIVE_TYPE_INTF || nativeType == NATIVE_TYPE_DEFAULT))
2530                     {
2531                         m_resID = IDS_EE_BADMARSHAL_NOLAYOUT;
2532                         IfFailGoto(E_FAIL, lFail);
2533                     }
2534 #ifdef FEATURE_COMINTEROP
2535                     // default marshalling is interface
2536                     m_type = MARSHAL_TYPE_INTERFACE;
2537 #else // FEATURE_COMINTEROP
2538                     m_resID = IDS_EE_OBJECT_TO_ITF_NOT_SUPPORTED;
2539                     IfFailGoto(E_FAIL, lFail);
2540 #endif // FEATURE_COMINTEROP
2541                 }
2542
2543                 else
2544                 {
2545                     _ASSERTE(m_pMT->IsValueType());
2546                     goto lValueClass;
2547                 }
2548             }
2549             break;
2550         }
2551
2552     
2553         case ELEMENT_TYPE_VALUETYPE:
2554         lValueClass:
2555         {
2556             if (sig.IsClassThrowing(pModule, g_DecimalClassName, pTypeContext))
2557             {
2558                 switch (nativeType)
2559                 {
2560                     case NATIVE_TYPE_DEFAULT:
2561                     case NATIVE_TYPE_STRUCT:
2562                         m_type = MARSHAL_TYPE_DECIMAL;
2563                         break;
2564
2565                     case NATIVE_TYPE_LPSTRUCT:
2566                         m_type = MARSHAL_TYPE_DECIMAL_PTR;
2567                         break;
2568
2569                     case NATIVE_TYPE_CURRENCY:
2570                         m_type = MARSHAL_TYPE_CURRENCY;
2571                         break;
2572
2573                     default:
2574                         m_resID = IDS_EE_BADMARSHALPARAM_DECIMAL;
2575                         IfFailGoto(E_FAIL, lFail);
2576                 }
2577             }
2578             else if (sig.IsClassThrowing(pModule, g_GuidClassName, pTypeContext))
2579             {
2580                 switch (nativeType)
2581                 {
2582                     case NATIVE_TYPE_DEFAULT:
2583                     case NATIVE_TYPE_STRUCT:
2584                         m_type = MARSHAL_TYPE_GUID;
2585                         break;
2586
2587                     case NATIVE_TYPE_LPSTRUCT:
2588                         m_type = MARSHAL_TYPE_GUID_PTR;
2589                         break;
2590
2591                     default:
2592                         m_resID = IDS_EE_BADMARSHAL_GUID;
2593                         IfFailGoto(E_FAIL, lFail);
2594                 }
2595             }
2596 #ifdef FEATURE_COMINTEROP
2597             else if (sig.IsClassThrowing(pModule, g_DateTimeOffsetClassName, pTypeContext))
2598             {
2599                 if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_STRUCT))
2600                 {
2601                     m_resID = IDS_EE_BADMARSHAL_DATETIMEOFFSET;
2602                     IfFailGoto(E_FAIL, lFail);
2603                 }
2604                 m_type = MARSHAL_TYPE_DATETIME;
2605                 m_pMT = MscorlibBinder::GetClass(CLASS__DATE_TIME_OFFSET);
2606             }           
2607 #endif  // FEATURE_COMINTEROP
2608             else if (sig.IsClassThrowing(pModule, g_DateClassName, pTypeContext))
2609             {
2610                 if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_STRUCT))
2611                 {
2612                     m_resID = IDS_EE_BADMARSHAL_DATETIME;
2613                     IfFailGoto(E_FAIL, lFail);
2614                 }
2615                 m_type = MARSHAL_TYPE_DATE;
2616             }
2617             else if (sig.IsClassThrowing(pModule, "System.Runtime.InteropServices.ArrayWithOffset", pTypeContext))
2618             {
2619                 if (!(nativeType == NATIVE_TYPE_DEFAULT))
2620                 {
2621                     IfFailGoto(E_FAIL, lFail);
2622                 }
2623                 m_type = MARSHAL_TYPE_ARRAYWITHOFFSET;
2624             }
2625             else if (sig.IsClassThrowing(pModule, "System.Runtime.InteropServices.HandleRef", pTypeContext))
2626             {
2627                 if (!(nativeType == NATIVE_TYPE_DEFAULT))
2628                 {
2629                     IfFailGoto(E_FAIL, lFail);
2630                 }
2631                 m_type = MARSHAL_TYPE_HANDLEREF;
2632             }
2633             else if (sig.IsClassThrowing(pModule, "System.ArgIterator", pTypeContext))
2634             {
2635                 if (!(nativeType == NATIVE_TYPE_DEFAULT))
2636                 {
2637                     IfFailGoto(E_FAIL, lFail);
2638                 }
2639                 m_type = MARSHAL_TYPE_ARGITERATOR;
2640             }
2641 #ifdef FEATURE_COMINTEROP
2642             else if (sig.IsClassThrowing(pModule, g_ColorClassName, pTypeContext))
2643             {
2644                 if (!(nativeType == NATIVE_TYPE_DEFAULT))
2645                 {
2646                     IfFailGoto(E_FAIL, lFail);
2647                 }
2648
2649                 // This is only supported for COM interop.
2650                 if (m_ms != MARSHAL_SCENARIO_COMINTEROP)
2651                 {
2652                     IfFailGoto(E_FAIL, lFail);
2653                 }
2654
2655                 m_type = MARSHAL_TYPE_OLECOLOR;
2656             }
2657 #endif // FEATURE_COMINTEROP
2658             else if (sig.IsClassThrowing(pModule, g_RuntimeTypeHandleClassName, pTypeContext))
2659             {
2660                 if (nativeType != NATIVE_TYPE_DEFAULT)
2661                 {
2662                     IfFailGoto(E_FAIL, lFail);
2663                 }
2664
2665                 m_type = MARSHAL_TYPE_RUNTIMETYPEHANDLE;
2666             }
2667             else if (sig.IsClassThrowing(pModule, g_RuntimeFieldHandleClassName, pTypeContext))
2668             {
2669                 if (nativeType != NATIVE_TYPE_DEFAULT)
2670                 {
2671                     IfFailGoto(E_FAIL, lFail);
2672                 }
2673
2674                 m_type = MARSHAL_TYPE_RUNTIMEFIELDHANDLE;
2675             }
2676             else if (sig.IsClassThrowing(pModule, g_RuntimeMethodHandleClassName, pTypeContext))
2677             {
2678                 if (nativeType != NATIVE_TYPE_DEFAULT)
2679                 {
2680                     IfFailGoto(E_FAIL, lFail);
2681                 }
2682
2683                 m_type = MARSHAL_TYPE_RUNTIMEMETHODHANDLE;
2684             }
2685             else
2686             {
2687                 m_pMT = sig.GetTypeHandleThrowing(pModule, pTypeContext).GetMethodTable();
2688                 if (m_pMT == NULL)
2689                     break;
2690
2691 #ifdef FEATURE_COMINTEROP
2692                 // Handle Nullable<T> and KeyValuePair<K, V> for WinRT
2693                 if (m_ms == MARSHAL_SCENARIO_WINRT)
2694                 {
2695                     if (m_pMT->HasSameTypeDefAs(g_pNullableClass))
2696                     {
2697                         m_type = MARSHAL_TYPE_NULLABLE;
2698                         m_args.m_pMT = m_pMT;
2699                         break;
2700                     }
2701
2702                     if (m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__KEYVALUEPAIRGENERIC)))
2703                     {
2704                         m_type = MARSHAL_TYPE_KEYVALUEPAIR;
2705                         m_args.m_pMT = m_pMT;
2706                         break;
2707                     }
2708
2709                     if (!m_pMT->IsLegalNonArrayWinRTType())
2710                     {
2711                         m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
2712                         IfFailGoto(E_FAIL, lFail);
2713                     }
2714                 }
2715 #endif // FEATURE_COMINTEROP
2716
2717                 if (m_pMT->HasInstantiation())
2718                 {
2719                     m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
2720                     IfFailGoto(E_FAIL, lFail);
2721                 }
2722
2723                 UINT managedSize = m_pMT->GetAlignedNumInstanceFieldBytes();
2724                 UINT  nativeSize = m_pMT->GetNativeSize();
2725                 
2726                 if ( nativeSize > 0xfff0 ||
2727                     managedSize > 0xfff0)
2728                 {
2729                     m_resID = IDS_EE_STRUCTTOOCOMPLEX;
2730                     IfFailGoto(E_FAIL, lFail);
2731                 }
2732
2733                 if (m_pMT->IsBlittable())
2734                 {
2735                     if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_STRUCT))
2736                     {
2737                         m_resID = IDS_EE_BADMARSHAL_VALUETYPE;
2738                         IfFailGoto(E_FAIL, lFail);
2739                     }
2740
2741                     if (m_byref && !isParam)
2742                     {
2743                         // Override the prohibition on byref returns so that IJW works
2744                         m_byref = FALSE;
2745                         m_type = ((sizeof(void*) == 4) ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8);
2746                     }
2747                     else
2748                     {
2749                         if (fNeedsCopyCtor)
2750                         {
2751 #ifdef FEATURE_COMINTEROP
2752                             if (m_ms == MARSHAL_SCENARIO_WINRT)
2753                             {
2754                                 // our WinRT-optimized GetCOMIPFromRCW helpers don't support copy
2755                                 // constructor stubs so make sure that this marshaler will not be used
2756                                 m_resID = IDS_EE_BADMARSHAL_WINRT_COPYCTOR;
2757                                 IfFailGoto(E_FAIL, lFail);
2758                             }
2759 #endif
2760
2761                             MethodDesc *pCopyCtor;
2762                             MethodDesc *pDtor;
2763                             FindCopyCtor(pModule, m_pMT, &pCopyCtor);
2764                             FindDtor(pModule, m_pMT, &pDtor);
2765
2766                             m_args.mm.m_pMT = m_pMT;
2767                             m_args.mm.m_pCopyCtor = pCopyCtor;
2768                             m_args.mm.m_pDtor = pDtor;
2769                             m_type = MARSHAL_TYPE_BLITTABLEVALUECLASSWITHCOPYCTOR;
2770                         }
2771                         else
2772 #ifdef _TARGET_X86_
2773                         // JIT64 is not aware of normalized value types and this optimization
2774                         // (returning small value types by value in registers) is already done in JIT64.
2775                         if (        !m_byref   // Permit register-sized structs as return values
2776                                  && !isParam
2777                                  && !onInstanceMethod
2778                                  && CorIsPrimitiveType(m_pMT->GetInternalCorElementType())
2779                                  && !IsUnmanagedValueTypeReturnedByRef(nativeSize)
2780                                  && managedSize <= sizeof(void*)
2781                                  && nativeSize <= sizeof(void*))
2782                         {
2783                             m_type = MARSHAL_TYPE_GENERIC_4;
2784                             m_args.m_pMT = m_pMT;
2785                         }
2786                         else
2787 #endif // _TARGET_X86_
2788                         {
2789                             m_args.m_pMT = m_pMT;
2790                             m_type = MARSHAL_TYPE_BLITTABLEVALUECLASS;
2791                         }
2792                     }
2793                 }
2794                 else if (m_pMT->HasLayout())
2795                 {
2796                     if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_STRUCT))
2797                     {
2798                         m_resID = IDS_EE_BADMARSHAL_VALUETYPE;
2799                         IfFailGoto(E_FAIL, lFail);
2800                     }
2801
2802                     m_args.m_pMT = m_pMT;
2803                     m_type = MARSHAL_TYPE_VALUECLASS;
2804                 }
2805             }
2806             break;
2807         }
2808     
2809         case ELEMENT_TYPE_SZARRAY:
2810         case ELEMENT_TYPE_ARRAY:
2811         {
2812             // Get class info from array.
2813             TypeHandle arrayTypeHnd = sig.GetTypeHandleThrowing(pModule, pTypeContext);
2814             _ASSERTE(!arrayTypeHnd.IsNull());
2815
2816             ArrayTypeDesc* asArray = arrayTypeHnd.AsArray();
2817             if (asArray == NULL)
2818                 IfFailGoto(E_FAIL, lFail);
2819
2820             TypeHandle thElement = asArray->GetTypeParam();
2821
2822 #ifdef FEATURE_COMINTEROP
2823             if (m_ms != MARSHAL_SCENARIO_WINRT)
2824 #endif // FEATURE_COMINTEROP
2825             {
2826                 if (thElement.HasInstantiation())
2827                 {
2828                     m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
2829                     IfFailGoto(E_FAIL, lFail);
2830                 }
2831             }
2832
2833             // Handle retrieving the information for the array type.
2834             IfFailGoto(HandleArrayElemType(&ParamInfo, thElement, asArray->GetRank(), mtype == ELEMENT_TYPE_SZARRAY, isParam, pAssembly), lFail);
2835             break;
2836         }
2837         
2838         default:
2839             m_resID = IDS_EE_BADMARSHAL_BADMANAGED;
2840     }
2841
2842 lExit:
2843 #ifdef FEATURE_COMINTEROP
2844 //Field scenario is not blocked here because we don't want to block loading structs that 
2845 //have the types which we are blocking, but never pass it to Interop.
2846
2847     if (AppX::IsAppXProcess() && ms != MarshalInfo::MARSHAL_SCENARIO_FIELD)
2848     {
2849         bool set_error = false;
2850         switch (m_type)
2851         {
2852             case MARSHAL_TYPE_ANSIBSTR: 
2853                 m_resID = IDS_EE_BADMARSHAL_TYPE_ANSIBSTR;
2854                 set_error = true;
2855                 break;
2856             case MARSHAL_TYPE_VBBYVALSTR:
2857             case MARSHAL_TYPE_VBBYVALSTRW:
2858                 m_resID = IDS_EE_BADMARSHAL_TYPE_VBBYVALSTR;
2859                 set_error = true;
2860                 break;
2861             case MARSHAL_TYPE_REFERENCECUSTOMMARSHALER:
2862                 m_resID = IDS_EE_BADMARSHAL_TYPE_REFERENCECUSTOMMARSHALER;
2863                 set_error = true;
2864                 break;
2865             case MARSHAL_TYPE_ASANYA: 
2866             case MARSHAL_TYPE_ASANYW: 
2867                 m_resID = IDS_EE_BADMARSHAL_TYPE_ASANYA;
2868                 set_error = true;
2869                 break;
2870             case MARSHAL_TYPE_INTERFACE:
2871                 if (m_fDispItf)
2872                 {
2873                     m_resID = IDS_EE_BADMARSHAL_TYPE_IDISPATCH;
2874                     set_error = true;
2875                 }
2876                 break;
2877         }
2878
2879         if (set_error)
2880             COMPlusThrow(kPlatformNotSupportedException, m_resID);
2881
2882     }
2883     
2884     if (IsWinRTScenario() && !IsSupportedForWinRT(m_type))
2885     {
2886         // the marshaler we came up with is not supported in WinRT scenarios
2887         m_type = MARSHAL_TYPE_UNKNOWN;
2888         m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
2889         goto lReallyExit;
2890     }
2891 #endif // FEATURE_COMINTEROP
2892
2893     if (m_byref && !isParam)
2894     {
2895         // byref returns don't work: the thing pointed to lives on
2896         // a stack that disappears!
2897         m_type = MARSHAL_TYPE_UNKNOWN;
2898         goto lReallyExit;
2899     }
2900    
2901     //---------------------------------------------------------------------
2902     // Now, figure out the IN/OUT status.
2903     // Also set the m_fOleVarArgCandidate here to save perf of invoking Metadata API
2904     //---------------------------------------------------------------------
2905     m_fOleVarArgCandidate = FALSE;
2906     if (m_type != MARSHAL_TYPE_UNKNOWN && IsInOnly(m_type) && !m_byref)
2907     {
2908         // If we got here, the parameter is something like an "int" where
2909         // [in] is the only semantically valid choice. Since there is no
2910         // possible way to interpret an [out] for such a type, we will ignore
2911         // the metadata and force the bits to "in". We could have defined
2912         // it as an error instead but this is less likely to cause problems
2913         // with metadata autogenerated from typelibs and poorly
2914         // defined C headers.
2915         // 
2916         m_in = TRUE;
2917         m_out = FALSE;
2918     }
2919     else
2920     {
2921
2922         // Capture and save away "In/Out" bits. If none is present, set both to FALSE (they will be properly defaulted downstream)
2923         if (token == mdParamDefNil)
2924         {
2925             m_in = FALSE;
2926             m_out = FALSE;
2927         }
2928         else if (TypeFromToken(token) != mdtParamDef)
2929         {
2930             _ASSERTE(TypeFromToken(token) == mdtFieldDef);
2931
2932             // Field setters are always In, the flags are ignored for return values of getters
2933             m_in = TRUE;
2934             m_out = FALSE;
2935         }
2936         else
2937         {
2938             IMDInternalImport *pInternalImport = pModule->GetMDImport();
2939             USHORT             usSequence;
2940             DWORD              dwAttr;
2941             LPCSTR             szParamName_Ignore;
2942             
2943             if (FAILED(pInternalImport->GetParamDefProps(token, &usSequence, &dwAttr, &szParamName_Ignore)))
2944             {
2945                 m_in = FALSE;
2946                 m_out = FALSE;
2947             }
2948             else
2949             {
2950                 m_in = IsPdIn(dwAttr) != 0;
2951                 m_out = IsPdOut(dwAttr) != 0;
2952 #ifdef FEATURE_COMINTEROP
2953                 // set m_fOleVarArgCandidate. The rule is same as the one defined in vm\tlbexp.cpp
2954                 if(paramidx == numArgs &&                   // arg is the last arg of the method
2955                    !(dwAttr & PARAMFLAG_FOPT) &&            // arg is not a optional arg
2956                    !IsNilToken(token) &&                    // token is not a nil token
2957                    (m_type == MARSHAL_TYPE_SAFEARRAY) &&    // arg is marshaled as SafeArray
2958                    (m_arrayElementType == VT_VARIANT))      // the element of the safearray is VARIANT
2959                 {
2960                     // check if it has default value
2961                     MDDefaultValue defaultValue;
2962                     if (SUCCEEDED(pInternalImport->GetDefaultValue(token, &defaultValue)) && defaultValue.m_bType == ELEMENT_TYPE_VOID)
2963                     {
2964                         // check if it has params attribute
2965                         if (pInternalImport->GetCustomAttributeByName(token, INTEROP_PARAMARRAY_TYPE, 0,0) == S_OK)
2966                             m_fOleVarArgCandidate = TRUE;
2967                     }
2968                 }
2969 #endif
2970             }
2971         }
2972         
2973         // If neither IN nor OUT are true, this signals the URT to use the default
2974         // rules.
2975         if (!m_in && !m_out)
2976         {
2977             if (m_byref || 
2978                  (mtype == ELEMENT_TYPE_CLASS 
2979                   && !(sig.IsStringType(pModule, pTypeContext))
2980                   && sig.IsClass(pModule, g_StringBufferClassName, pTypeContext)))
2981             {
2982                 m_in = TRUE;
2983                 m_out = TRUE;
2984             }
2985             else
2986             {
2987                 m_in = TRUE;
2988                 m_out = FALSE;
2989             }
2990         
2991         }
2992     }
2993     
2994 lReallyExit:
2995     
2996 #ifdef _DEBUG
2997     DumpMarshalInfo(pModule, sig, pTypeContext, token, ms, nlType, nlFlags); 
2998 #endif
2999     return;
3000     
3001     
3002   lFail:
3003     // We got here because of an illegal ELEMENT_TYPE/NATIVE_TYPE combo.
3004     m_type = MARSHAL_TYPE_UNKNOWN;
3005     //_ASSERTE(!"Invalid ELEMENT_TYPE/NATIVE_TYPE combination");
3006     goto lExit;
3007 }
3008 #ifdef _PREFAST_
3009 #pragma warning(pop)
3010 #endif
3011
3012 VOID MarshalInfo::EmitOrThrowInteropParamException(NDirectStubLinker* psl, BOOL fMngToNative, UINT resID, UINT paramIdx)
3013 {
3014     CONTRACTL
3015     {
3016         THROWS;
3017         GC_TRIGGERS;
3018         MODE_ANY;
3019     }
3020     CONTRACTL_END;
3021
3022 #ifdef FEATURE_COMINTEROP
3023     // If this is not forward COM interop, throw the exception right away. We rely on this
3024     // for example in code:ComPreStubWorker when we fire the InvalidMemberDeclaration MDA.
3025     if ((m_ms == MARSHAL_SCENARIO_COMINTEROP || m_ms == MARSHAL_SCENARIO_WINRT) && fMngToNative)
3026     {
3027         psl->SetInteropParamExceptionInfo(resID, paramIdx);
3028         return;
3029     }
3030 #endif // FEATURE_COMINTEROP
3031
3032     ThrowInteropParamException(resID, paramIdx);
3033 }
3034
3035
3036 HRESULT MarshalInfo::HandleArrayElemType(NativeTypeParamInfo *pParamInfo, TypeHandle thElement, int iRank, BOOL fNoLowerBounds, BOOL isParam, Assembly *pAssembly)
3037 {
3038     CONTRACTL
3039     {
3040         STANDARD_VM_CHECK;
3041         PRECONDITION(CheckPointer(pParamInfo));
3042     }
3043     CONTRACTL_END;
3044
3045     ArrayMarshalInfo arrayMarshalInfo(amiRuntime);
3046     
3047
3048     //
3049     // Store rank and bound information.
3050     //
3051
3052     m_iArrayRank = iRank;
3053     m_nolowerbounds = fNoLowerBounds;
3054
3055
3056     //
3057     // Determine which type of marshaler to use.
3058     //
3059
3060 #ifdef FEATURE_COMINTEROP
3061     if (m_ms == MARSHAL_SCENARIO_WINRT)
3062     {
3063         m_type = MARSHAL_TYPE_HIDDENLENGTHARRAY;
3064     }
3065     else if (pParamInfo->m_NativeType == NATIVE_TYPE_SAFEARRAY)
3066     {
3067         m_type = MARSHAL_TYPE_SAFEARRAY;
3068     }
3069     else
3070 #endif // FEATURE_COMINTEROP
3071     if (pParamInfo->m_NativeType == NATIVE_TYPE_ARRAY)
3072     {
3073         m_type = MARSHAL_TYPE_NATIVEARRAY;
3074     }
3075     else if (pParamInfo->m_NativeType == NATIVE_TYPE_DEFAULT)
3076     {
3077 #ifdef FEATURE_COMINTEROP
3078         if (m_ms != MARSHAL_SCENARIO_NDIRECT)
3079         {
3080             m_type = MARSHAL_TYPE_SAFEARRAY;
3081         }
3082         else
3083 #endif // FEATURE_COMINTEROP
3084         {
3085             m_type = MARSHAL_TYPE_NATIVEARRAY;
3086         }
3087     }
3088     else
3089     {
3090         m_resID = IDS_EE_BADMARSHAL_ARRAY;
3091         return E_FAIL;
3092     }
3093
3094 #ifdef FEATURE_COMINTEROP
3095     if (m_type == MARSHAL_TYPE_SAFEARRAY)
3096     {
3097         arrayMarshalInfo.InitForSafeArray(m_ms, thElement, pParamInfo->m_SafeArrayElementVT, m_fAnsi);
3098     }
3099     else if (m_type == MARSHAL_TYPE_HIDDENLENGTHARRAY)
3100     {
3101         arrayMarshalInfo.InitForHiddenLengthArray(thElement);
3102     }
3103     else
3104 #endif // FEATURE_COMINTEROP
3105     {
3106         _ASSERTE(m_type == MARSHAL_TYPE_NATIVEARRAY);
3107         arrayMarshalInfo.InitForNativeArray(m_ms, thElement, pParamInfo->m_ArrayElementType, m_fAnsi);
3108     }
3109
3110     // Make sure the marshalling information is valid.
3111     if (!arrayMarshalInfo.IsValid())
3112     {
3113         m_resID = arrayMarshalInfo.GetErrorResourceId();
3114         return E_FAIL;
3115     }
3116
3117     // Set the array type handle and VARTYPE to use for marshalling.
3118     m_hndArrayElemType = arrayMarshalInfo.GetElementTypeHandle();
3119     m_arrayElementType = arrayMarshalInfo.GetElementVT();
3120
3121     if (m_type == MARSHAL_TYPE_NATIVEARRAY)
3122     {
3123         // Retrieve the extra information associated with the native array marshaling.
3124         m_args.na.m_vt  = m_arrayElementType;
3125         m_countParamIdx = pParamInfo->m_CountParamIdx;
3126         m_multiplier    = pParamInfo->m_Multiplier;
3127         m_additive      = pParamInfo->m_Additive;
3128     }
3129 #ifdef FEATURE_COMINTEROP
3130     else if (m_type == MARSHAL_TYPE_HIDDENLENGTHARRAY)
3131     {
3132         m_args.na.m_vt  = m_arrayElementType;
3133         m_args.na.m_cbElementSize = arrayMarshalInfo.GetElementSize();
3134         m_args.na.m_redirectedTypeIndex = arrayMarshalInfo.GetRedirectedTypeIndex();
3135     }
3136 #endif // FEATURE_COMINTEROP
3137
3138     return S_OK;
3139 }
3140
3141 ILMarshaler* CreateILMarshaler(MarshalInfo::MarshalType mtype, NDirectStubLinker* psl)
3142 {
3143     CONTRACTL
3144     {
3145         THROWS;
3146         GC_NOTRIGGER;
3147         MODE_ANY;
3148     }
3149     CONTRACTL_END;
3150     ILMarshaler* pMarshaler = NULL;
3151     switch (mtype)
3152     {
3153
3154 #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) \
3155         case MarshalInfo::mt: \
3156             pMarshaler = new IL##mclass(); \
3157             break; 
3158 #include "mtypes.h"
3159 #undef DEFINE_MARSHALER_TYPE
3160
3161         default:
3162             UNREACHABLE_MSG("unexpected MarshalType passed to CreateILMarshaler");
3163     }
3164
3165     pMarshaler->SetNDirectStubLinker(psl);
3166     return pMarshaler;
3167 }
3168
3169
3170
3171 DWORD CalculateArgumentMarshalFlags(BOOL byref, BOOL in, BOOL out, BOOL fMngToNative)
3172 {
3173     LIMITED_METHOD_CONTRACT;
3174     DWORD dwMarshalFlags = 0;
3175
3176     if (byref)
3177     {
3178         dwMarshalFlags |= MARSHAL_FLAG_BYREF;
3179     }
3180
3181     if (in)
3182     {
3183         dwMarshalFlags |= MARSHAL_FLAG_IN;
3184     }
3185
3186     if (out)
3187     {
3188         dwMarshalFlags |= MARSHAL_FLAG_OUT;
3189     }
3190
3191     if (fMngToNative)
3192     {
3193         dwMarshalFlags |= MARSHAL_FLAG_CLR_TO_NATIVE;
3194     }
3195
3196     return dwMarshalFlags;
3197 }
3198
3199 DWORD CalculateReturnMarshalFlags(BOOL hrSwap, BOOL fMngToNative)
3200 {
3201     LIMITED_METHOD_CONTRACT;
3202     DWORD dwMarshalFlags = MARSHAL_FLAG_RETVAL;
3203
3204     if (hrSwap)
3205     {
3206         dwMarshalFlags |= MARSHAL_FLAG_HRESULT_SWAP;
3207     }
3208
3209     if (fMngToNative)
3210     {
3211         dwMarshalFlags |= MARSHAL_FLAG_CLR_TO_NATIVE;
3212     }
3213
3214     return dwMarshalFlags;
3215 }
3216
3217 void MarshalInfo::GenerateArgumentIL(NDirectStubLinker* psl,
3218                                      int argOffset, // the argument's index is m_paramidx + argOffset
3219                                      UINT nativeStackOffset, // offset of the argument on the native stack
3220                                      BOOL fMngToNative)
3221 {
3222     CONTRACTL
3223     {
3224         STANDARD_VM_CHECK;
3225         PRECONDITION(CheckPointer(psl));
3226     }
3227     CONTRACTL_END;
3228
3229     if (m_type == MARSHAL_TYPE_UNKNOWN)
3230     {
3231         EmitOrThrowInteropParamException(psl, fMngToNative, m_resID, m_paramidx + 1); // m_paramidx is 0-based, but the user wants to see a 1-based index
3232         return;
3233     }
3234
3235     // set up m_corArgSize and m_nativeArgSize
3236     SetupArgumentSizes();
3237
3238     MarshalerOverrideStatus amostat;
3239     UINT resID = IDS_EE_BADMARSHAL_RESTRICTION;
3240     amostat = (GetArgumentOverrideProc(m_type)) (psl,
3241                                              m_byref,
3242                                              m_in,
3243                                              m_out,
3244                                              fMngToNative,
3245                                              &m_args,
3246                                              &resID,
3247                                              m_paramidx + argOffset,
3248                                              nativeStackOffset);
3249
3250
3251     if (amostat == OVERRIDDEN)
3252     {
3253         return;
3254     }
3255     
3256     if (amostat == DISALLOWED)
3257     {
3258         EmitOrThrowInteropParamException(psl, fMngToNative, resID, m_paramidx + 1); // m_paramidx is 0-based, but the user wants to see a 1-based index
3259         return;
3260     }
3261
3262     CONSISTENCY_CHECK(amostat == HANDLEASNORMAL);
3263
3264     NewHolder<ILMarshaler> pMarshaler = CreateILMarshaler(m_type, psl);
3265     DWORD dwMarshalFlags = CalculateArgumentMarshalFlags(m_byref, m_in, m_out, fMngToNative);
3266
3267     if (!pMarshaler->SupportsArgumentMarshal(dwMarshalFlags, &resID))
3268     {
3269         EmitOrThrowInteropParamException(psl, fMngToNative, resID, m_paramidx + 1); // m_paramidx is 0-based, but the user wants to see a 1-based index
3270         return;
3271     }
3272
3273     ILCodeStream* pcsMarshal    = psl->GetMarshalCodeStream();
3274     ILCodeStream* pcsUnmarshal  = psl->GetUnmarshalCodeStream();
3275     ILCodeStream* pcsDispatch   = psl->GetDispatchCodeStream();
3276
3277     pcsMarshal->EmitNOP("// argument { ");
3278     pcsUnmarshal->EmitNOP("// argument { ");
3279
3280     pMarshaler->EmitMarshalArgument(pcsMarshal, pcsUnmarshal, m_paramidx + argOffset, dwMarshalFlags, &m_args);
3281
3282     //
3283     // Increment a counter so that when the finally clause 
3284     // is run, we only run the cleanup that is needed.
3285     //
3286     if (pMarshaler->NeedsMarshalCleanupIndex())
3287     {
3288         // we don't bother writing to the counter if marshaling does not need cleanup
3289         psl->EmitSetArgMarshalIndex(pcsMarshal, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_paramidx + argOffset);
3290     }
3291     if (pMarshaler->NeedsUnmarshalCleanupIndex())
3292     {
3293         // we don't bother writing to the counter if unmarshaling does not need exception cleanup
3294         psl->EmitSetArgMarshalIndex(pcsUnmarshal, NDirectStubLinker::CLEANUP_INDEX_ARG0_UNMARSHAL + m_paramidx + argOffset);
3295     }
3296
3297     pcsMarshal->EmitNOP("// } argument");
3298     pcsUnmarshal->EmitNOP("// } argument");
3299
3300     pMarshaler->EmitSetupArgument(pcsDispatch);
3301     if (m_paramidx == 0)
3302     {
3303         CorCallingConvention callConv = psl->GetStubTargetCallingConv();
3304         if ((callConv & IMAGE_CEE_CS_CALLCONV_MASK) == IMAGE_CEE_UNMANAGED_CALLCONV_THISCALL)
3305         {
3306             // Make sure the 'this' argument to thiscall is of native int type; JIT asserts this.
3307             pcsDispatch->EmitCONV_I();
3308         }
3309     }
3310 }
3311
3312 void MarshalInfo::GenerateReturnIL(NDirectStubLinker* psl,
3313                                    int argOffset,
3314                                    BOOL fMngToNative,
3315                                    BOOL fieldGetter,
3316                                    BOOL retval)
3317 {
3318     CONTRACTL
3319     {
3320         STANDARD_VM_CHECK;
3321         PRECONDITION(CheckPointer(psl));
3322     }
3323     CONTRACTL_END;
3324     
3325     MarshalerOverrideStatus amostat;
3326     UINT resID = IDS_EE_BADMARSHAL_RESTRICTION;
3327
3328     if (m_type == MARSHAL_TYPE_UNKNOWN)
3329     {
3330         amostat = HANDLEASNORMAL;
3331     }
3332     else
3333     {
3334         amostat = (GetReturnOverrideProc(m_type)) (psl,
3335                                                    fMngToNative,
3336                                                    retval,
3337                                                    &m_args,
3338                                                    &resID);
3339     }
3340
3341     if (amostat == DISALLOWED)
3342     {
3343         EmitOrThrowInteropParamException(psl, fMngToNative, resID, 0);
3344         return;
3345     }
3346         
3347     if (amostat == HANDLEASNORMAL)
3348     {
3349         // Historically we have always allowed reading fields that are marshaled as C arrays.
3350         if (m_type == MARSHAL_TYPE_UNKNOWN || (!fieldGetter && m_type == MARSHAL_TYPE_NATIVEARRAY))
3351         {
3352             EmitOrThrowInteropParamException(psl, fMngToNative, m_resID, 0);
3353             return;
3354         }
3355     
3356         NewHolder<ILMarshaler> pMarshaler = CreateILMarshaler(m_type, psl);
3357         DWORD dwMarshalFlags = CalculateReturnMarshalFlags(retval, fMngToNative);
3358
3359         if (!pMarshaler->SupportsReturnMarshal(dwMarshalFlags, &resID))
3360         {
3361             EmitOrThrowInteropParamException(psl, fMngToNative, resID, 0);
3362             return;
3363         }
3364
3365         ILCodeStream* pcsMarshal    = psl->GetMarshalCodeStream();
3366         ILCodeStream* pcsUnmarshal  = psl->GetReturnUnmarshalCodeStream();
3367         ILCodeStream* pcsDispatch   = psl->GetDispatchCodeStream();
3368             
3369         pcsMarshal->EmitNOP("// return { ");
3370         pcsUnmarshal->EmitNOP("// return { ");
3371             
3372         UINT16 wNativeSize = GetNativeSize(m_type, m_ms);
3373
3374         // The following statement behaviour has existed for a long time. By aligning the size of the return
3375         // value up to stack slot size, we prevent EmitMarshalReturnValue from distinguishing between, say, 3-byte
3376         // structure and 4-byte structure. The former is supposed to be returned by-ref using a secret argument
3377         // (at least in MSVC compiled code) while the latter is returned in EAX. We are keeping the behavior for
3378         // now for backward compatibility.
3379         X86_ONLY(wNativeSize = StackElemSize(wNativeSize));
3380
3381         pMarshaler->EmitMarshalReturnValue(pcsMarshal, pcsUnmarshal, pcsDispatch, m_paramidx + argOffset, wNativeSize, dwMarshalFlags, &m_args);
3382
3383         pcsMarshal->EmitNOP("// } return");
3384         pcsUnmarshal->EmitNOP("// } return");
3385
3386         return;
3387     }
3388 }
3389
3390 void MarshalInfo::SetupArgumentSizes()
3391 {
3392     CONTRACTL
3393     {
3394         NOTHROW;
3395         GC_NOTRIGGER;
3396         MODE_ANY;
3397     }
3398     CONTRACTL_END;
3399
3400     if (m_byref)
3401     {
3402         m_managedArgSize = StackElemSize(sizeof(void*));
3403         m_nativeArgSize = StackElemSize(sizeof(void*));
3404     }
3405     else
3406     {
3407         m_managedArgSize = StackElemSize(GetManagedSize(m_type, m_ms));
3408         m_nativeArgSize = StackElemSize(GetNativeSize(m_type, m_ms));
3409     }
3410
3411 #ifdef ENREGISTERED_PARAMTYPE_MAXSIZE
3412     if (m_managedArgSize > ENREGISTERED_PARAMTYPE_MAXSIZE)
3413         m_managedArgSize = StackElemSize(sizeof(void*));
3414
3415     if (m_nativeArgSize > ENREGISTERED_PARAMTYPE_MAXSIZE)
3416         m_nativeArgSize = StackElemSize(sizeof(void*));
3417 #endif // ENREGISTERED_PARAMTYPE_MAXSIZE
3418 }
3419
3420 UINT16 MarshalInfo::GetManagedSize(MarshalType mtype, MarshalScenario ms)
3421 {
3422     CONTRACTL
3423     {
3424         NOTHROW;
3425         GC_NOTRIGGER;
3426         MODE_ANY;
3427     }
3428     CONTRACTL_END;
3429     
3430     static const BYTE managedSizes[]=
3431     {
3432         #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) IL##mclass::c_CLRSize,
3433         #include "mtypes.h"
3434     };
3435
3436     _ASSERTE((SIZE_T)mtype < COUNTOF(managedSizes));
3437     BYTE managedSize = managedSizes[mtype];
3438
3439     if (managedSize == VARIABLESIZE)
3440     {
3441         switch (mtype)
3442         {
3443
3444             case MARSHAL_TYPE_BLITTABLEVALUECLASS:
3445             case MARSHAL_TYPE_VALUECLASS:
3446 #ifdef FEATURE_COMINTEROP
3447             case MARSHAL_TYPE_DATETIME:
3448             case MARSHAL_TYPE_NULLABLE:
3449             case MARSHAL_TYPE_KEYVALUEPAIR:
3450 #endif // FEATURE_COMINTEROP
3451                 return (UINT16) m_pMT->GetAlignedNumInstanceFieldBytes();
3452                 break;
3453
3454             default:
3455                 _ASSERTE(0);
3456         }
3457     }
3458
3459     return managedSize;
3460 }
3461
3462 UINT16 MarshalInfo::GetNativeSize(MarshalType mtype, MarshalScenario ms)
3463 {
3464     CONTRACTL
3465     {
3466         NOTHROW;
3467         GC_NOTRIGGER;
3468         MODE_ANY;
3469     }
3470     CONTRACTL_END;
3471     
3472     static const BYTE nativeSizes[]=
3473     {
3474         #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) IL##mclass::c_nativeSize,
3475         #include "mtypes.h"
3476     };
3477
3478     _ASSERTE((SIZE_T)mtype < COUNTOF(nativeSizes));
3479     BYTE nativeSize = nativeSizes[mtype];
3480
3481     if (nativeSize == VARIABLESIZE)
3482     {
3483         switch (mtype)
3484         {
3485             case MARSHAL_TYPE_BLITTABLEVALUECLASS:
3486             case MARSHAL_TYPE_VALUECLASS:
3487             case MARSHAL_TYPE_BLITTABLEVALUECLASSWITHCOPYCTOR:
3488                 return (UINT16) m_pMT->GetNativeSize();
3489
3490             default:
3491                 _ASSERTE(0);
3492         }
3493     }
3494
3495     return nativeSize;
3496 }
3497
3498 bool MarshalInfo::IsInOnly(MarshalType mtype)
3499 {
3500     CONTRACTL
3501     {
3502         NOTHROW;
3503         GC_NOTRIGGER;
3504         MODE_ANY;
3505     }
3506     CONTRACTL_END;
3507     
3508     static const bool ILMarshalerIsInOnly[] =
3509     {
3510         #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) \
3511             (IL##mclass::c_fInOnly ? true : false),
3512
3513         #include "mtypes.h"
3514     };
3515
3516     return ILMarshalerIsInOnly[mtype];
3517 }
3518
3519 bool MarshalInfo::IsSupportedForWinRT(MarshalType mtype)
3520 {
3521     CONTRACTL
3522     {
3523         NOTHROW;
3524         GC_NOTRIGGER;
3525         MODE_ANY;
3526     }
3527     CONTRACTL_END;
3528     
3529     static const bool MarshalerSupportsWinRT[] =
3530     {
3531         #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) \
3532             fWinRTSupported,
3533
3534         #include "mtypes.h"
3535     };
3536
3537     return MarshalerSupportsWinRT[mtype];
3538 }
3539
3540 OVERRIDEPROC MarshalInfo::GetArgumentOverrideProc(MarshalType mtype)
3541 {
3542     CONTRACTL
3543     {
3544         NOTHROW;
3545         GC_NOTRIGGER;
3546         MODE_ANY;
3547     }
3548     CONTRACTL_END;
3549     
3550     static const OVERRIDEPROC ILArgumentOverrideProcs[] =
3551     {
3552         #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) IL##mclass::ArgumentOverride,
3553         #include "mtypes.h"
3554     };
3555
3556     _ASSERTE((SIZE_T)mtype < COUNTOF(ILArgumentOverrideProcs));
3557     return ILArgumentOverrideProcs[mtype];
3558 }
3559
3560 RETURNOVERRIDEPROC MarshalInfo::GetReturnOverrideProc(MarshalType mtype)
3561 {
3562     CONTRACTL
3563     {
3564         NOTHROW;
3565         GC_NOTRIGGER;
3566         MODE_ANY;
3567     }
3568     CONTRACTL_END;
3569     
3570     static const RETURNOVERRIDEPROC ILReturnOverrideProcs[] =
3571     {
3572         #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) IL##mclass::ReturnOverride,
3573         #include "mtypes.h"
3574     };
3575
3576     _ASSERTE((SIZE_T)mtype < COUNTOF(ILReturnOverrideProcs));
3577     return ILReturnOverrideProcs[mtype];
3578 }
3579
3580 void MarshalInfo::GetItfMarshalInfo(ItfMarshalInfo* pInfo)
3581 {
3582     STANDARD_VM_CONTRACT;
3583
3584     GetItfMarshalInfo(TypeHandle(m_pMT),
3585 #ifdef FEATURE_COMINTEROP
3586         TypeHandle(m_pDefaultItfMT),
3587 #else // FEATURE_COMINTEROP
3588         TypeHandle(),
3589 #endif // FEATURE_COMINTEROP
3590         m_fDispItf,
3591         m_fInspItf,
3592         m_ms,
3593         pInfo);
3594 }
3595
3596 void MarshalInfo::GetItfMarshalInfo(TypeHandle th, TypeHandle thItf, BOOL fDispItf, BOOL fInspItf, MarshalScenario ms, ItfMarshalInfo *pInfo)
3597 {
3598     CONTRACTL
3599     {
3600         THROWS;
3601         GC_TRIGGERS;
3602         MODE_ANY;
3603         PRECONDITION(CheckPointer(pInfo));
3604         PRECONDITION(!th.IsNull());
3605         PRECONDITION(!th.IsTypeDesc());
3606     }
3607     CONTRACTL_END;
3608
3609 #ifdef FEATURE_COMINTEROP
3610
3611     // Initialize the output parameter.
3612     pInfo->dwFlags = 0;
3613     pInfo->thItf = TypeHandle();
3614     pInfo->thClass = TypeHandle();
3615
3616     if (!th.IsInterface())
3617     {
3618         // If the parameter is not System.Object.
3619         if (!th.IsObjectType())
3620         {
3621             // Set the class method table.
3622             pInfo->thClass = th;
3623
3624             if (th.IsTypeDesc() || !th.AsMethodTable()->IsWinRTDelegate())
3625             {
3626                 // If this is not a WinRT delegate, retrieve the default interface method table.
3627                 TypeHandle hndDefItfClass;
3628                 DefaultInterfaceType DefItfType;
3629            
3630                 if (!thItf.IsNull())
3631                 {
3632                     hndDefItfClass = thItf;
3633                     DefItfType = DefaultInterfaceType_Explicit;
3634                 }
3635                 else if (th.IsProjectedFromWinRT() || th.IsExportedToWinRT())
3636                 {
3637                     // WinRT classes use their WinRT default interface
3638                     hndDefItfClass = th.GetMethodTable()->GetDefaultWinRTInterface();
3639                     DefItfType = DefaultInterfaceType_Explicit;
3640                 }
3641                 else
3642                 {
3643                     DefItfType = GetDefaultInterfaceForClassWrapper(th, &hndDefItfClass);
3644                 }
3645                 switch (DefItfType)
3646                 {
3647                     case DefaultInterfaceType_Explicit:
3648                     {
3649                         pInfo->thItf = hndDefItfClass;
3650                         switch (hndDefItfClass.GetComInterfaceType())
3651                         {
3652                             case ifDispatch:
3653                             case ifDual:
3654                                 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3655                                 break;
3656
3657                             case ifInspectable:
3658                                 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;
3659                                 break;
3660                         }
3661                         break;
3662                     }
3663
3664                     case DefaultInterfaceType_AutoDual:
3665                     {
3666                         pInfo->thItf = hndDefItfClass;
3667                         pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3668                         break;
3669                     }
3670
3671                     case DefaultInterfaceType_IUnknown:
3672                     case DefaultInterfaceType_BaseComClass:
3673                     {
3674                         break;
3675                     }
3676
3677                     case DefaultInterfaceType_AutoDispatch:
3678                     {
3679                         pInfo->thItf = hndDefItfClass;
3680                         pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3681                         break;
3682                     }
3683
3684                     default:
3685                     {
3686                         _ASSERTE(!"Invalid default interface type!");
3687                         break;
3688                     }
3689                 }
3690             }
3691         }
3692         else
3693         {
3694             // The type will be marshalled as an IUnknown, IInspectable, or IDispatch pointer depending
3695             // on the value of fDispItf and fInspItf
3696             if (fDispItf)
3697             {
3698                 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3699             }
3700             else if (fInspItf)
3701             {
3702                 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;
3703             }
3704             
3705             pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_USE_BASIC_ITF;
3706         }
3707     }
3708     else if (fInspItf)
3709     {
3710         // IInspectable-based interfaces are simple
3711         pInfo->thItf = th;
3712         pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;
3713     }
3714     else
3715     {
3716         // Determine the interface this type will be marshalled as. 
3717         if (th.IsComClassInterface())
3718             pInfo->thItf = th.GetDefItfForComClassItf();
3719         else
3720             pInfo->thItf = th;
3721
3722         // Determine if we are dealing with an IDispatch, IInspectable, or IUnknown based interface.
3723         switch (pInfo->thItf.GetComInterfaceType())
3724         {
3725             case ifDispatch:
3726             case ifDual:
3727                 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3728                 break;
3729
3730             case ifInspectable:
3731                 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;
3732                 break;
3733         }
3734
3735         // Look to see if the interface has a coclass defined
3736         pInfo->thClass = th.GetCoClassForInterface();
3737         if (!pInfo->thClass.IsNull())
3738         {
3739             pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_CLASS_IS_HINT;
3740         }
3741     }
3742
3743     // store the pre-redirection interface type as thNativeItf
3744     pInfo->thNativeItf = pInfo->thItf;
3745
3746     if (ms == MARSHAL_SCENARIO_WINRT)
3747     {
3748         // Use the "class is hint" flag so GetObjectRefFromComIP doesn't verify that the
3749         // WinRT object really supports IInspectable - note that we'll do the verification
3750         // in UnmarshalObjectFromInterface for this exact pInfo->thItf.
3751         pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_CLASS_IS_HINT;
3752
3753         pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_WINRT_SCENARIO;
3754         
3755         // Perform interface redirection statically here. When the resulting ItfMarshalInfo
3756         // is used for CLR->WinRT marshaling, this is necessary so we know which COM vtable
3757         // to pass out (for instance IList could be marshaled out as IList or IBindableVector
3758         // depending on the marshal scenario). In the WinRT->CLR direction, it's just an
3759         // optimization which saves us from performing redirection at run-time.
3760
3761         if (!pInfo->thItf.IsNull())
3762         {
3763             MethodTable *pNewItfMT1;
3764             MethodTable *pNewItfMT2;
3765             switch (RCW::GetInterfacesForQI(pInfo->thItf.GetMethodTable(), &pNewItfMT1, &pNewItfMT2))
3766             {
3767                 case RCW::InterfaceRedirection_None:
3768                 case RCW::InterfaceRedirection_UnresolvedIEnumerable:
3769                     break;
3770
3771                 case RCW::InterfaceRedirection_IEnumerable_RetryOnFailure:
3772                 case RCW::InterfaceRedirection_IEnumerable:
3773                 case RCW::InterfaceRedirection_Other:
3774                     pInfo->thNativeItf = pNewItfMT1;
3775                     break;
3776
3777                 case RCW::InterfaceRedirection_Other_RetryOnFailure:
3778                     pInfo->thNativeItf = pNewItfMT2;
3779                     break;
3780             }
3781         }
3782
3783         if (!pInfo->thNativeItf.IsNull())
3784         {
3785             // The native interface is redirected WinRT interface - need to change the flags
3786             _ASSERTE(pInfo->thNativeItf.AsMethodTable()->IsProjectedFromWinRT());
3787             
3788             pInfo->dwFlags &= ~ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3789             pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;            
3790         }
3791     }
3792
3793 #else // FEATURE_COMINTEROP
3794     if (!th.IsInterface())
3795         pInfo->thClass = th;
3796     else
3797         pInfo->thItf = th;
3798 #endif // FEATURE_COMINTEROP
3799 }
3800
3801 HRESULT MarshalInfo::TryGetItfMarshalInfo(TypeHandle th, BOOL fDispItf, BOOL fInspItf, ItfMarshalInfo *pInfo)
3802 {
3803     CONTRACTL
3804     {
3805         STANDARD_VM_CHECK;
3806         PRECONDITION(!th.IsNull());
3807         PRECONDITION(CheckPointer(pInfo));
3808     }
3809     CONTRACTL_END;
3810
3811     HRESULT hr = S_OK;
3812
3813     EX_TRY
3814     {
3815         GetItfMarshalInfo(th, TypeHandle(), fDispItf, fInspItf,
3816 #ifdef FEATURE_COMINTEROP
3817             MARSHAL_SCENARIO_COMINTEROP,
3818 #else // FEATURE_COMINTEROP
3819             MARSHAL_SCENARIO_NDIRECT,
3820 #endif // FEATURE_COMINTEROP
3821             pInfo);
3822     }
3823     EX_CATCH
3824     {
3825         hr = GET_EXCEPTION()->GetHR();
3826     }
3827     EX_END_CATCH(RethrowTerminalExceptions);
3828     
3829     return hr;
3830 }
3831
3832 #ifdef _DEBUG
3833 VOID MarshalInfo::DumpMarshalInfo(Module* pModule, SigPointer sig, const SigTypeContext *pTypeContext, mdToken token,
3834                                   MarshalScenario ms, CorNativeLinkType nlType, CorNativeLinkFlags nlFlags)
3835 {
3836     CONTRACTL
3837     {
3838         THROWS;
3839         GC_TRIGGERS;
3840         MODE_ANY;
3841     }
3842     CONTRACTL_END;
3843     
3844     if (LoggingOn(LF_MARSHALER, LL_INFO10))
3845     {
3846         SString logbuf;
3847         StackScratchBuffer scratch;
3848
3849         IMDInternalImport *pInternalImport = pModule->GetMDImport();
3850
3851         logbuf.AppendASCII("------------------------------------------------------------\n");
3852         LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch)));
3853         logbuf.Clear();
3854         
3855         logbuf.AppendASCII("Managed type: ");
3856         if (m_byref)
3857             logbuf.AppendASCII("Byref ");
3858
3859         TypeHandle th = sig.GetTypeHandleNT(pModule, pTypeContext);
3860         if (th.IsNull())
3861             logbuf.AppendASCII("<error>");
3862         else
3863         {
3864             SigFormat sigfmt;
3865             sigfmt.AddType(th);
3866             logbuf.AppendUTF8(sigfmt.GetCString());
3867         }
3868
3869         logbuf.AppendASCII("\n");
3870         LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch)));
3871         logbuf.Clear();
3872
3873         logbuf.AppendASCII("NativeType  : ");
3874         PCCOR_SIGNATURE pvNativeType;
3875         ULONG           cbNativeType;
3876         if (token == mdParamDefNil
3877             || pInternalImport->GetFieldMarshal(token,
3878                                                  &pvNativeType,
3879                                                  &cbNativeType) != S_OK)
3880         {
3881             logbuf.AppendASCII("<absent>");
3882         }
3883         else
3884         {
3885
3886             while (cbNativeType--)
3887             {
3888                 char num[100];
3889                 sprintf_s(num, COUNTOF(num), "0x%lx ", (ULONG)*pvNativeType);
3890                 logbuf.AppendASCII(num);
3891                 switch (*(pvNativeType++))
3892                 {
3893 #define XXXXX(nt) case nt: logbuf.AppendASCII("(" #nt ")"); break;
3894
3895                     XXXXX(NATIVE_TYPE_BOOLEAN)     
3896                     XXXXX(NATIVE_TYPE_I1)          
3897
3898                     XXXXX(NATIVE_TYPE_U1)
3899                     XXXXX(NATIVE_TYPE_I2)          
3900                     XXXXX(NATIVE_TYPE_U2)          
3901                     XXXXX(NATIVE_TYPE_I4)          
3902
3903                     XXXXX(NATIVE_TYPE_U4)
3904                     XXXXX(NATIVE_TYPE_I8)          
3905                     XXXXX(NATIVE_TYPE_U8)          
3906                     XXXXX(NATIVE_TYPE_R4)          
3907
3908                     XXXXX(NATIVE_TYPE_R8)
3909
3910                     XXXXX(NATIVE_TYPE_LPSTR)
3911                     XXXXX(NATIVE_TYPE_LPWSTR)      
3912                     XXXXX(NATIVE_TYPE_LPTSTR)      
3913                     XXXXX(NATIVE_TYPE_FIXEDSYSSTRING)
3914
3915                     XXXXX(NATIVE_TYPE_STRUCT)      
3916
3917                     XXXXX(NATIVE_TYPE_INT)         
3918                     XXXXX(NATIVE_TYPE_FIXEDARRAY)
3919
3920                     XXXXX(NATIVE_TYPE_UINT)
3921                 
3922                     XXXXX(NATIVE_TYPE_FUNC)
3923                 
3924                     XXXXX(NATIVE_TYPE_ASANY)
3925
3926                     XXXXX(NATIVE_TYPE_ARRAY)
3927                     XXXXX(NATIVE_TYPE_LPSTRUCT)
3928
3929                     XXXXX(NATIVE_TYPE_IUNKNOWN)
3930
3931                     XXXXX(NATIVE_TYPE_BSTR)
3932 #ifdef FEATURE_COMINTEROP
3933                     XXXXX(NATIVE_TYPE_TBSTR)
3934                     XXXXX(NATIVE_TYPE_ANSIBSTR)
3935                     XXXXX(NATIVE_TYPE_HSTRING)
3936                     XXXXX(NATIVE_TYPE_BYVALSTR)
3937
3938                     XXXXX(NATIVE_TYPE_VARIANTBOOL)
3939                     XXXXX(NATIVE_TYPE_SAFEARRAY)
3940
3941                     XXXXX(NATIVE_TYPE_IDISPATCH)
3942                     XXXXX(NATIVE_TYPE_INTF)
3943 #endif // FEATURE_COMINTEROP
3944
3945 #undef XXXXX
3946
3947                     
3948                     case NATIVE_TYPE_CUSTOMMARSHALER:
3949                     {
3950                         int strLen = 0;
3951                         logbuf.AppendASCII("(NATIVE_TYPE_CUSTOMMARSHALER)");
3952
3953                         // Skip the typelib guid.
3954                         logbuf.AppendASCII(" ");
3955
3956                         strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType);
3957                         if (strLen)
3958                         {
3959                             BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen);
3960                             memcpyNoGCRefs(p, pvNativeType, strLen);
3961                             logbuf.CloseBuffer();
3962                             logbuf.AppendASCII("\0");
3963
3964                             pvNativeType += strLen;
3965                             cbNativeType -= strLen + 1;
3966
3967                             // Skip the name of the native type.
3968                             logbuf.AppendASCII(" ");
3969                         }
3970                         
3971                         
3972                         strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType);
3973                         if (strLen)
3974                         {
3975                             BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen);
3976                             memcpyNoGCRefs(p, pvNativeType, strLen);
3977                             logbuf.CloseBuffer();
3978                             logbuf.AppendASCII("\0");
3979                             
3980                             pvNativeType += strLen;
3981                             cbNativeType -= strLen + 1;
3982                             
3983                             // Extract the name of the custom marshaler.
3984                             logbuf.AppendASCII(" ");
3985                         }
3986                         
3987                         
3988                         strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType);
3989                         if (strLen)
3990                         {
3991                             BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen);
3992                             memcpyNoGCRefs(p, pvNativeType, strLen);
3993                             logbuf.CloseBuffer();
3994                             logbuf.AppendASCII("\0");
3995                         
3996                             pvNativeType += strLen;
3997                             cbNativeType -= strLen + 1;
3998         
3999                             // Extract the cookie string.
4000                             logbuf.AppendASCII(" ");
4001                         }
4002                         
4003                         strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType);
4004                         if (strLen)
4005                         {
4006                             BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen);
4007                             memcpyNoGCRefs(p, pvNativeType, strLen);
4008                             logbuf.CloseBuffer();
4009                             logbuf.AppendASCII("\0");
4010
4011                             pvNativeType += strLen;
4012                             cbNativeType -= strLen + 1;
4013                         }
4014                         
4015                         break;
4016                     }
4017
4018                     default:
4019                         logbuf.AppendASCII("(?)");
4020                 }
4021
4022                 logbuf.AppendASCII("   ");
4023             }
4024         }
4025         logbuf.AppendASCII("\n");
4026         LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch)));
4027         logbuf.Clear();
4028
4029         logbuf.AppendASCII("MarshalType : ");
4030         {
4031             char num[100];
4032             sprintf_s(num, COUNTOF(num), "0x%lx ", (ULONG)m_type);
4033             logbuf.AppendASCII(num);
4034         }
4035         switch (m_type)
4036         {
4037             #define DEFINE_MARSHALER_TYPE(mt, mc, fWinRTSupported) case mt: logbuf.AppendASCII( #mt " (IL" #mc ")"); break;
4038             #include "mtypes.h"
4039
4040             case MARSHAL_TYPE_UNKNOWN:
4041                 logbuf.AppendASCII("MARSHAL_TYPE_UNKNOWN (illegal combination)");
4042                 break;
4043                 
4044             default:
4045                 logbuf.AppendASCII("MARSHAL_TYPE_???");
4046                 break;
4047         }
4048         
4049         logbuf.AppendASCII("\n");
4050         
4051         
4052         logbuf.AppendASCII("Metadata In/Out     : ");
4053         if (TypeFromToken(token) != mdtParamDef || token == mdParamDefNil)
4054             logbuf.AppendASCII("<absent>");
4055         
4056         else
4057         {
4058             DWORD dwAttr = 0;
4059             USHORT usSequence;
4060             LPCSTR szParamName_Ignore;
4061             if (FAILED(pInternalImport->GetParamDefProps(token, &usSequence, &dwAttr, &szParamName_Ignore)))
4062             {
4063                 logbuf.AppendASCII("Invalid ParamDef record ");
4064             }
4065             else
4066             {
4067                 if (IsPdIn(dwAttr))
4068                     logbuf.AppendASCII("In ");
4069                 
4070                 if (IsPdOut(dwAttr))
4071                     logbuf.AppendASCII("Out ");
4072             }
4073         }
4074         
4075         logbuf.AppendASCII("\n");
4076         
4077         logbuf.AppendASCII("Effective In/Out     : ");
4078         if (m_in)
4079             logbuf.AppendASCII("In ");
4080         
4081         if (m_out)
4082             logbuf.AppendASCII("Out ");
4083         
4084         logbuf.AppendASCII("\n");
4085         
4086         LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch)));
4087         logbuf.Clear();
4088     }
4089 } // MarshalInfo::DumpMarshalInfo
4090 #endif //_DEBUG
4091
4092 #ifndef CROSSGEN_COMPILE
4093 #ifdef FEATURE_COMINTEROP
4094 DispParamMarshaler *MarshalInfo::GenerateDispParamMarshaler()
4095 {
4096     CONTRACT (DispParamMarshaler*)
4097     {
4098         THROWS;
4099         GC_TRIGGERS;
4100         MODE_ANY;
4101         INJECT_FAULT(COMPlusThrowOM());
4102         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
4103     }
4104     CONTRACT_END;
4105
4106     NewHolder<DispParamMarshaler> pDispParamMarshaler = NULL;
4107
4108     switch (m_type)
4109     {
4110         case MARSHAL_TYPE_OLECOLOR:
4111             pDispParamMarshaler = new DispParamOleColorMarshaler();
4112             break;
4113
4114         case MARSHAL_TYPE_CURRENCY:
4115             pDispParamMarshaler = new DispParamCurrencyMarshaler();
4116             break;
4117
4118         case MARSHAL_TYPE_GENERIC_4:
4119             if (m_fErrorNativeType)
4120                 pDispParamMarshaler = new DispParamErrorMarshaler();
4121             break;
4122
4123         case MARSHAL_TYPE_INTERFACE:
4124         {
4125             ItfMarshalInfo itfInfo;
4126             GetItfMarshalInfo(TypeHandle(m_pMT), TypeHandle(m_pDefaultItfMT), m_fDispItf, m_fInspItf, m_ms, &itfInfo);
4127             pDispParamMarshaler = new DispParamInterfaceMarshaler(
4128                 itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF, 
4129                 itfInfo.thItf.GetMethodTable(), 
4130                 itfInfo.thClass.GetMethodTable(), 
4131                 itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_CLASS_IS_HINT);
4132             break;
4133         }
4134
4135         case MARSHAL_TYPE_VALUECLASS:
4136         case MARSHAL_TYPE_BLITTABLEVALUECLASS:
4137         case MARSHAL_TYPE_BLITTABLEPTR:
4138         case MARSHAL_TYPE_LAYOUTCLASSPTR:
4139         case MARSHAL_TYPE_BLITTABLEVALUECLASSWITHCOPYCTOR:
4140             pDispParamMarshaler = new DispParamRecordMarshaler(m_pMT);
4141             break;
4142
4143 #ifdef FEATURE_CLASSIC_COMINTEROP
4144         case MARSHAL_TYPE_SAFEARRAY:
4145             pDispParamMarshaler = new DispParamArrayMarshaler(m_arrayElementType, m_hndArrayElemType.GetMethodTable());
4146             break;
4147 #endif
4148
4149         case MARSHAL_TYPE_DELEGATE:
4150             pDispParamMarshaler = new DispParamDelegateMarshaler(m_pMT);
4151             break;
4152             
4153         case MARSHAL_TYPE_REFERENCECUSTOMMARSHALER:
4154             pDispParamMarshaler = new DispParamCustomMarshaler(m_pCMHelper, m_CMVt);
4155             break;
4156     }
4157
4158     pDispParamMarshaler.SuppressRelease();
4159     RETURN pDispParamMarshaler;
4160 }
4161
4162
4163 DispatchWrapperType MarshalInfo::GetDispWrapperType()
4164 {
4165     STANDARD_VM_CONTRACT;
4166     
4167     DispatchWrapperType WrapperType = (DispatchWrapperType)0;
4168
4169     switch (m_type)
4170     {
4171         case MARSHAL_TYPE_CURRENCY:
4172             WrapperType = DispatchWrapperType_Currency;
4173             break;
4174
4175         case MARSHAL_TYPE_BSTR:
4176             WrapperType = DispatchWrapperType_BStr;
4177             break;
4178
4179         case MARSHAL_TYPE_GENERIC_4:
4180             if (m_fErrorNativeType)
4181                 WrapperType = DispatchWrapperType_Error;
4182             break;
4183
4184         case MARSHAL_TYPE_INTERFACE:
4185         {
4186             ItfMarshalInfo itfInfo;
4187             GetItfMarshalInfo(TypeHandle(m_pMT), TypeHandle(m_pDefaultItfMT), m_fDispItf, m_fInspItf, m_ms, &itfInfo);
4188             WrapperType = !!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF) ? DispatchWrapperType_Dispatch : DispatchWrapperType_Unknown;
4189             break;
4190         }
4191     
4192         case MARSHAL_TYPE_SAFEARRAY:
4193             switch (m_arrayElementType)
4194             {
4195                 case VT_CY:
4196                     WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_Currency);
4197                     break;
4198                 case VT_UNKNOWN:
4199                     WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_Unknown);
4200                     break;
4201                 case VT_DISPATCH:
4202                     WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_Dispatch);
4203                     break;
4204                 case VT_ERROR:
4205                     WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_Error);
4206                     break;
4207                 case VT_BSTR:
4208                     WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_BStr);
4209                     break;
4210             }
4211             break;
4212     }
4213
4214     return WrapperType;
4215 }
4216
4217 #endif // FEATURE_COMINTEROP
4218
4219
4220 VOID MarshalInfo::MarshalTypeToString(SString& strMarshalType, BOOL fSizeIsSpecified)
4221 {
4222     CONTRACTL
4223     {
4224         THROWS;
4225         GC_TRIGGERS;
4226         MODE_ANY;
4227     }
4228     CONTRACTL_END;
4229     
4230     LPCWSTR strRetVal;
4231
4232     if (m_type == MARSHAL_TYPE_NATIVEARRAY)
4233     {
4234         SString strVarType;
4235         VarTypeToString(m_arrayElementType, strVarType);
4236
4237         if (!fSizeIsSpecified)
4238         {
4239             strMarshalType.Printf(W("native array of %s (size not specified by a parameter)"),
4240                                   strVarType.GetUnicode());
4241         }
4242         else
4243         {
4244             strMarshalType.Printf(W("native array of %s (size specified by parameter %i)"),
4245                                   strVarType.GetUnicode(), m_countParamIdx);
4246         }
4247
4248         return;
4249     }
4250 #ifdef FEATURE_COMINTEROP
4251     // Some MarshalTypes have extra information and require special handling
4252     else if (m_type == MARSHAL_TYPE_INTERFACE)
4253     {
4254         ItfMarshalInfo itfInfo;
4255         GetItfMarshalInfo(TypeHandle(m_pMT), TypeHandle(m_pDefaultItfMT), m_fDispItf, m_fInspItf, m_ms, &itfInfo);
4256
4257         if (!itfInfo.thItf.IsNull())
4258         {
4259             StackSString ssClassName;
4260             itfInfo.thItf.GetMethodTable()->_GetFullyQualifiedNameForClass(ssClassName);
4261
4262             if (!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF))
4263             {
4264                 strMarshalType.SetLiteral(W("IDispatch "));
4265             }
4266             else if (!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_INSP_ITF))
4267             {
4268                 strMarshalType.SetLiteral(W("IInspectable"));
4269             }
4270             else
4271             {
4272                 strMarshalType.SetLiteral(W("IUnknown "));
4273             }
4274
4275             if (itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_USE_BASIC_ITF)
4276             {
4277                 strMarshalType.Append(W("(basic) "));
4278             }
4279
4280             strMarshalType.Append(ssClassName);
4281             return;
4282         }
4283         else
4284         {
4285             if (!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF))
4286                 strRetVal = W("IDispatch");
4287             else if (!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_INSP_ITF))
4288                 strRetVal = W("IInspectable");
4289             else
4290                 strRetVal = W("IUnknown");
4291         }
4292     }
4293     else if (m_type == MARSHAL_TYPE_SAFEARRAY)
4294     {
4295         StackSString strVarType;
4296         VarTypeToString(m_arrayElementType, strVarType);
4297
4298         strMarshalType = SL(W("SafeArray of "));
4299         strMarshalType.Append(strVarType);
4300
4301         return;
4302     }
4303 #endif // FEATURE_COMINTEROP
4304     else if (m_type == MARSHAL_TYPE_REFERENCECUSTOMMARSHALER)
4305     {
4306         GCX_COOP();
4307         
4308         OBJECTHANDLE objHandle = m_pCMHelper->GetCustomMarshalerInfo()->GetCustomMarshaler();
4309         {
4310             OBJECTREF pObjRef = ObjectFromHandle(objHandle);
4311             DefineFullyQualifiedNameForClassW();
4312
4313             strMarshalType.Printf(W("custom marshaler (%s)"),
4314                                   GetFullyQualifiedNameForClassW(pObjRef->GetMethodTable()));
4315         }        
4316         
4317         return;
4318     }
4319     else
4320     {
4321         // All other MarshalTypes with no special handling
4322         switch (m_type)
4323         {
4324             case MARSHAL_TYPE_GENERIC_1:
4325                 strRetVal = W("BYTE");
4326                 break;
4327             case MARSHAL_TYPE_GENERIC_U1:
4328                 strRetVal = W("unsigned BYTE");
4329                 break;
4330             case MARSHAL_TYPE_GENERIC_2:
4331                 strRetVal = W("WORD");
4332                 break;
4333             case MARSHAL_TYPE_GENERIC_U2:
4334                 strRetVal = W("unsigned WORD");
4335                 break;
4336             case MARSHAL_TYPE_GENERIC_4:
4337                 strRetVal = W("DWORD");
4338                 break;
4339             case MARSHAL_TYPE_GENERIC_8:
4340                 strRetVal = W("QUADWORD");
4341                 break;
4342             case MARSHAL_TYPE_WINBOOL:
4343                 strRetVal = W("Windows Bool");
4344                 break;
4345 #ifdef FEATURE_COMINTEROP
4346             case MARSHAL_TYPE_VTBOOL:
4347                 strRetVal = W("VARIANT Bool");
4348                 break;
4349 #endif // FEATURE_COMINTEROP
4350             case MARSHAL_TYPE_ANSICHAR:
4351                 strRetVal = W("Ansi character");
4352                 break;
4353             case MARSHAL_TYPE_CBOOL:
4354                 strRetVal = W("CBool");
4355                 break;
4356             case MARSHAL_TYPE_FLOAT:
4357                 strRetVal = W("float");
4358                 break;
4359             case MARSHAL_TYPE_DOUBLE:
4360                 strRetVal = W("double");
4361                 break;
4362             case MARSHAL_TYPE_CURRENCY:
4363                 strRetVal = W("CURRENCY");
4364                 break;
4365             case MARSHAL_TYPE_DECIMAL:
4366                 strRetVal = W("DECIMAL");
4367                 break;
4368             case MARSHAL_TYPE_DECIMAL_PTR:
4369                 strRetVal = W("DECIMAL pointer");
4370                 break;
4371             case MARSHAL_TYPE_GUID:
4372                 strRetVal = W("GUID");
4373                 break;
4374             case MARSHAL_TYPE_GUID_PTR:
4375                 strRetVal = W("GUID pointer");
4376                 break;
4377             case MARSHAL_TYPE_DATE:
4378                 strRetVal = W("DATE");
4379                 break;
4380              case MARSHAL_TYPE_BSTR:
4381                 strRetVal = W("BSTR");
4382                 break;
4383             case MARSHAL_TYPE_LPWSTR:
4384                 strRetVal = W("LPWSTR");
4385                 break;
4386             case MARSHAL_TYPE_LPSTR:
4387                 strRetVal = W("LPSTR");
4388                 break;
4389             case MARSHAL_TYPE_LPUTF8STR:
4390                 strRetVal = W("LPUTF8STR");
4391                 break;
4392 #ifdef FEATURE_COMINTEROP
4393             case MARSHAL_TYPE_ANSIBSTR:
4394                 strRetVal = W("AnsiBStr");
4395                 break;
4396 #endif // FEATURE_COMINTEROP
4397             case MARSHAL_TYPE_LPWSTR_BUFFER:
4398                 strRetVal = W("LPWSTR buffer");
4399                 break;
4400             case MARSHAL_TYPE_LPSTR_BUFFER:
4401                 strRetVal = W("LPSTR buffer");
4402                 break;
4403             case MARSHAL_TYPE_UTF8_BUFFER:
4404                 strRetVal = W("UTF8 buffer");
4405                 break;
4406             case MARSHAL_TYPE_ASANYA:
4407                 strRetVal = W("AsAnyA");
4408                 break;
4409             case MARSHAL_TYPE_ASANYW:
4410                 strRetVal = W("AsAnyW");
4411                 break;
4412             case MARSHAL_TYPE_DELEGATE:
4413                 strRetVal = W("Delegate");
4414                 break;
4415             case MARSHAL_TYPE_BLITTABLEPTR:
4416                 strRetVal = W("blittable pointer");
4417                 break;
4418 #ifdef FEATURE_COMINTEROP
4419             case MARSHAL_TYPE_VBBYVALSTR:
4420                 strRetVal = W("VBByValStr");
4421                 break;
4422             case MARSHAL_TYPE_VBBYVALSTRW:
4423                 strRetVal = W("VBByRefStr");
4424                 break;
4425 #endif // FEATURE_COMINTEROP
4426             case MARSHAL_TYPE_LAYOUTCLASSPTR:
4427                 strRetVal = W("Layout class pointer");
4428                 break;
4429             case MARSHAL_TYPE_ARRAYWITHOFFSET:
4430                 strRetVal = W("ArrayWithOffset");
4431                 break;
4432             case MARSHAL_TYPE_BLITTABLEVALUECLASS:
4433                 strRetVal = W("blittable value class");
4434                 break;
4435             case MARSHAL_TYPE_VALUECLASS:
4436                 strRetVal = W("value class");
4437                 break;
4438             case MARSHAL_TYPE_ARGITERATOR:
4439                 strRetVal = W("ArgIterator");
4440                 break;
4441             case MARSHAL_TYPE_BLITTABLEVALUECLASSWITHCOPYCTOR:
4442                 strRetVal = W("blittable value class with copy constructor");
4443                 break;
4444 #ifdef FEATURE_COMINTEROP
4445             case MARSHAL_TYPE_OBJECT:
4446                 strRetVal = W("VARIANT");
4447                 break;
4448 #endif // FEATURE_COMINTEROP
4449             case MARSHAL_TYPE_HANDLEREF:
4450                 strRetVal = W("HandleRef");
4451                 break;
4452 #ifdef FEATURE_COMINTEROP
4453             case MARSHAL_TYPE_OLECOLOR:
4454                 strRetVal = W("OLE_COLOR");
4455                 break;
4456 #endif // FEATURE_COMINTEROP
4457             case MARSHAL_TYPE_RUNTIMETYPEHANDLE:
4458                 strRetVal = W("RuntimeTypeHandle");
4459                 break;
4460             case MARSHAL_TYPE_RUNTIMEFIELDHANDLE:
4461                 strRetVal = W("RuntimeFieldHandle");
4462                 break;
4463             case MARSHAL_TYPE_RUNTIMEMETHODHANDLE:
4464                 strRetVal = W("RuntimeMethodHandle");
4465                 break;
4466             case MARSHAL_TYPE_RUNTIMEMETHODINFO:
4467                 strRetVal = W("RuntimeMethodInfo");
4468                 break;
4469             case MARSHAL_TYPE_RUNTIMEMODULE:
4470                 strRetVal = W("RuntimeModule");
4471                 break;
4472             case MARSHAL_TYPE_RUNTIMEASSEMBLY:
4473                 strRetVal = W("RuntimeAssembly");
4474                 break;
4475             default:
4476                 strRetVal = W("<UNKNOWN>");
4477                 break;
4478         }
4479     }
4480
4481     strMarshalType.Set(strRetVal);
4482     return;
4483 }
4484
4485 VOID MarshalInfo::VarTypeToString(VARTYPE vt, SString& strVarType)
4486 {
4487     CONTRACTL
4488     {
4489         THROWS;
4490         GC_NOTRIGGER;
4491         MODE_ANY;
4492     }
4493     CONTRACTL_END;
4494
4495     
4496     LPCWSTR strRetVal;
4497     
4498     switch(vt)
4499     {
4500         case VT_I2:
4501             strRetVal = W("2-byte signed int");
4502             break;
4503         case VT_I4:
4504             strRetVal = W("4-byte signed int");
4505             break;
4506         case VT_R4:
4507             strRetVal = W("4-byte real");
4508             break;
4509         case VT_R8:
4510             strRetVal = W("8-byte real");
4511             break;
4512         case VT_CY:
4513             strRetVal = W("currency");
4514             break;
4515         case VT_DATE:
4516             strRetVal = W("date");
4517             break;
4518         case VT_BSTR:
4519             strRetVal = W("binary string");
4520             break;
4521         case VT_DISPATCH:
4522             strRetVal = W("IDispatch *");
4523             break;
4524         case VT_ERROR:
4525             strRetVal = W("Scode");
4526             break;
4527         case VT_BOOL:
4528             strRetVal = W("boolean");
4529             break;
4530         case VT_VARIANT:
4531             strRetVal = W("VARIANT *");
4532             break;
4533         case VT_UNKNOWN:
4534             strRetVal = W("IUnknown *");
4535             break;
4536         case VT_DECIMAL:
4537             strRetVal = W("16-byte fixed point");
4538             break;
4539         case VT_RECORD:
4540             strRetVal = W("user defined structure");
4541             break;
4542         case VT_I1:
4543             strRetVal = W("signed char");
4544             break;
4545         case VT_UI1:
4546             strRetVal = W("unsigned char");
4547             break;
4548         case VT_UI2:
4549             strRetVal = W("unsigned short");
4550             break;
4551         case VT_UI4:
4552             strRetVal = W("unsigned short");
4553             break;
4554         case VT_INT:
4555             strRetVal = W("signed int");
4556             break;
4557         case VT_UINT:
4558             strRetVal = W("unsigned int");
4559             break;
4560         case VT_LPSTR:
4561             strRetVal = W("LPSTR");
4562             break;
4563         case VT_LPWSTR:
4564             strRetVal = W("LPWSTR");
4565             break;
4566         case VT_HRESULT:
4567             strRetVal = W("HResult");
4568             break;
4569         case VT_I8:
4570             strRetVal = W("8-byte signed int");
4571             break;
4572         case VT_NULL:
4573             strRetVal = W("null");
4574             break;
4575         case VT_UI8:
4576             strRetVal = W("8-byte unsigned int");
4577             break;
4578         case VT_VOID:
4579             strRetVal = W("void");
4580             break;
4581         case VTHACK_WINBOOL:
4582             strRetVal = W("boolean");
4583             break;
4584         case VTHACK_ANSICHAR:
4585             strRetVal = W("char");
4586             break;
4587         case VTHACK_CBOOL:
4588             strRetVal = W("1-byte C bool");
4589             break;
4590         default:
4591             strRetVal = W("unknown");
4592             break;
4593     }
4594
4595     strVarType.Set(strRetVal);    
4596     return;
4597 }
4598
4599 #endif // CROSSGEN_COMPILE
4600
4601 // Returns true if the marshaler represented by this instance requires COM to have been started.
4602 bool MarshalInfo::MarshalerRequiresCOM()
4603 {
4604     LIMITED_METHOD_CONTRACT;
4605
4606 #ifdef FEATURE_COMINTEROP
4607     switch (m_type)
4608     {
4609         case MARSHAL_TYPE_REFERENCECUSTOMMARSHALER:
4610
4611         case MARSHAL_TYPE_BSTR:
4612         case MARSHAL_TYPE_ANSIBSTR:
4613         case MARSHAL_TYPE_OBJECT:
4614         case MARSHAL_TYPE_OLECOLOR:
4615         case MARSHAL_TYPE_SAFEARRAY:
4616         case MARSHAL_TYPE_INTERFACE:
4617
4618         case MARSHAL_TYPE_URI:
4619         case MARSHAL_TYPE_KEYVALUEPAIR:
4620         case MARSHAL_TYPE_NULLABLE:
4621         case MARSHAL_TYPE_SYSTEMTYPE:
4622         case MARSHAL_TYPE_EXCEPTION:
4623         case MARSHAL_TYPE_HIDDENLENGTHARRAY:
4624         case MARSHAL_TYPE_HSTRING:
4625         case MARSHAL_TYPE_NCCEVENTARGS:
4626         case MARSHAL_TYPE_PCEVENTARGS:
4627         {
4628             // some of these types do not strictly require COM for the actual marshaling
4629             // but they tend to be used in COM context so we keep the logic we had in
4630             // previous versions and return true here
4631             return true;
4632         }
4633         
4634         case MARSHAL_TYPE_LAYOUTCLASSPTR:
4635         case MARSHAL_TYPE_VALUECLASS:
4636         {
4637             // pessimistic guess, but in line with previous versions            
4638             return true;
4639         }
4640
4641         case MARSHAL_TYPE_NATIVEARRAY:
4642         {
4643             return (m_arrayElementType == VT_UNKNOWN ||
4644                     m_arrayElementType == VT_DISPATCH ||
4645                     m_arrayElementType == VT_VARIANT);
4646         }
4647     }
4648 #endif // FEATURE_COMINTEROP
4649
4650     return false;
4651 }
4652
4653 #ifdef FEATURE_COMINTEROP
4654 MarshalInfo::MarshalType MarshalInfo::GetHiddenLengthParamMarshalType()
4655 {
4656     LIMITED_METHOD_CONTRACT;
4657     return MARSHAL_TYPE_GENERIC_U4;
4658 }
4659
4660 CorElementType MarshalInfo::GetHiddenLengthParamElementType()
4661 {
4662     LIMITED_METHOD_CONTRACT;
4663     return ELEMENT_TYPE_U4;
4664 }
4665
4666 UINT16 MarshalInfo::GetHiddenLengthParamStackSize()
4667 {
4668     LIMITED_METHOD_CONTRACT;
4669     return StackElemSize(GetNativeSize(GetHiddenLengthParamMarshalType(), m_ms));
4670 }
4671
4672 void MarshalInfo::MarshalHiddenLengthArgument(NDirectStubLinker *psl, BOOL managedToNative, BOOL isForReturnArray)
4673 {
4674     CONTRACTL
4675     {
4676         STANDARD_VM_CHECK;
4677         PRECONDITION(CheckPointer(psl));
4678         PRECONDITION(m_type == MARSHAL_TYPE_HIDDENLENGTHARRAY);
4679         PRECONDITION(m_dwHiddenLengthManagedHomeLocal == 0xFFFFFFFF);
4680         PRECONDITION(m_dwHiddenLengthNativeHomeLocal == 0xFFFFFFFF);
4681     }
4682     CONTRACTL_END;
4683         
4684     NewHolder<ILMarshaler> pHiddenLengthMarshaler = CreateILMarshaler(GetHiddenLengthParamMarshalType(), psl);
4685
4686
4687     ILCodeStream *pcsMarshal = psl->GetMarshalCodeStream();
4688     ILCodeStream *pcsUnmarshal = psl->GetUnmarshalCodeStream();
4689
4690     pcsMarshal->EmitNOP("// hidden length argument { ");
4691     pcsUnmarshal->EmitNOP("// hidden length argument { ");
4692
4693     DWORD dwMarshalFlags = MARSHAL_FLAG_HIDDENLENPARAM;
4694     if (isForReturnArray)
4695     {
4696         // This is a hidden length argument for an [out, retval] argument, so setup flags to match that
4697         dwMarshalFlags |= CalculateArgumentMarshalFlags(TRUE, FALSE, TRUE, managedToNative);
4698     }
4699     else
4700     {
4701         // The length parameter needs to be an [in] parameter if the array itself is an [in] parameter.
4702         // Additionally, in order to support the FillArray pattern:
4703         //   FillArray([in] UInt32 length, [out, size_is(length)] ElementType* value)
4704         //
4705         // We need to make sure that the length parameter is [in] if the array pointer is not byref, since
4706         // this means that the caller is allocating the array.  This includes array buffers which are [out]
4707         // but not byref, since the [out] marshaling applies to the array contents but not the array pointer
4708         // value itself.
4709         BOOL marshalHiddenLengthIn = m_in || !m_byref;
4710         dwMarshalFlags |= CalculateArgumentMarshalFlags(m_byref, marshalHiddenLengthIn, m_out, managedToNative);
4711     }
4712     pHiddenLengthMarshaler->EmitMarshalHiddenLengthArgument(pcsMarshal,
4713                                                             pcsUnmarshal,
4714                                                             this,
4715                                                             m_paramidx,
4716                                                             dwMarshalFlags,
4717                                                             HiddenLengthParamIndex(),
4718                                                             &m_args,
4719                                                             &m_dwHiddenLengthManagedHomeLocal,
4720                                                             &m_dwHiddenLengthNativeHomeLocal);
4721
4722     pcsMarshal->EmitNOP("// } hidden length argument");
4723     pcsUnmarshal->EmitNOP("// } hidden length argument");
4724
4725     // Only emit into the dispatch stream for CLR -> Native cases - in the reverse, there is no argument
4726     // to pass to the managed method.  Instead, the length is encoded in the marshaled array.
4727     if (managedToNative)
4728     {
4729         ILCodeStream* pcsDispatch = psl->GetDispatchCodeStream();
4730         pHiddenLengthMarshaler->EmitSetupArgument(pcsDispatch);
4731     }
4732 }
4733
4734 #endif // FEATURE_COMINTEROP
4735
4736 #define ReportInvalidArrayMarshalInfo(resId)    \
4737     do                                          \
4738     {                                           \
4739         m_vtElement = VT_EMPTY;                 \
4740         m_errorResourceId = resId;              \
4741         m_thElement = TypeHandle();             \
4742         goto LExit;                             \
4743     }                                           \
4744     while (0)                                   
4745
4746 void ArrayMarshalInfo::InitForNativeArray(MarshalInfo::MarshalScenario ms, TypeHandle thElement, CorNativeType ntElement, BOOL isAnsi)
4747 {
4748     WRAPPER_NO_CONTRACT;        
4749     InitElementInfo(NATIVE_TYPE_ARRAY, ms, thElement, ntElement, isAnsi);
4750 }
4751
4752 void ArrayMarshalInfo::InitForFixedArray(TypeHandle thElement, CorNativeType ntElement, BOOL isAnsi)
4753 {
4754     WRAPPER_NO_CONTRACT;        
4755     InitElementInfo(NATIVE_TYPE_FIXEDARRAY, MarshalInfo::MARSHAL_SCENARIO_FIELD, thElement, ntElement, isAnsi);
4756 }
4757
4758 #ifdef FEATURE_COMINTEROP    
4759 void ArrayMarshalInfo::InitForSafeArray(MarshalInfo::MarshalScenario ms, TypeHandle thElement, VARTYPE vtElement, BOOL isAnsi)
4760 {
4761     STANDARD_VM_CONTRACT;
4762     
4763     InitElementInfo(NATIVE_TYPE_SAFEARRAY, ms, thElement, NATIVE_TYPE_DEFAULT, isAnsi);
4764
4765     if (IsValid() && vtElement != VT_EMPTY)
4766     {
4767         if (vtElement == VT_USERDEFINED)
4768         {
4769             // If the user explicitly sets the VARTYPE to VT_USERDEFINED, we simply ignore it 
4770             // since the exporter will take care of transforming the vt to VT_USERDEFINED and the 
4771             // marshallers needs the actual type.
4772         }
4773         else
4774         {
4775             m_flags = (ArrayMarshalInfoFlags)(m_flags | amiSafeArraySubTypeExplicitlySpecified);
4776             m_vtElement = vtElement;
4777         }
4778     }
4779 }
4780
4781 void ArrayMarshalInfo::InitForHiddenLengthArray(TypeHandle thElement)
4782 {
4783     STANDARD_VM_CONTRACT;
4784     
4785     MethodTable *pMT = NULL;
4786
4787     // WinRT supports arrays of any WinRT-legal types
4788     if (thElement.IsArray())
4789     {
4790         ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_NESTEDARRAY);
4791     }
4792     else if (thElement.IsTypeDesc() || !thElement.GetMethodTable()->IsLegalNonArrayWinRTType())
4793     {
4794         ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE);
4795     }
4796
4797     m_thElement = thElement;
4798
4799     pMT = thElement.GetMethodTable();
4800     if (pMT->IsString())
4801     {
4802         m_vtElement = VTHACK_HSTRING;
4803         m_cbElementSize = sizeof(HSTRING);
4804     }
4805     else if (WinRTTypeNameConverter::ResolveRedirectedType(pMT, &m_redirectedTypeIndex))
4806     {
4807         m_vtElement = VTHACK_REDIRECTEDTYPE;
4808
4809         switch (m_redirectedTypeIndex)
4810         {
4811             case WinMDAdapter::RedirectedTypeIndex_System_DateTimeOffset:
4812                 m_cbElementSize = ILDateTimeMarshaler::c_nativeSize;
4813                 break;
4814
4815             case WinMDAdapter::RedirectedTypeIndex_System_Type:
4816                 m_cbElementSize = ILSystemTypeMarshaler::c_nativeSize;
4817                 break;
4818
4819             case WinMDAdapter::RedirectedTypeIndex_System_Exception:
4820                 m_cbElementSize = ILHResultExceptionMarshaler::c_nativeSize;
4821                 break;
4822
4823                 // WinRT delegates are IUnknown pointers
4824             case WinMDAdapter::RedirectedTypeIndex_System_EventHandlerGeneric:
4825                 m_vtElement = VTHACK_INSPECTABLE;
4826                 m_cbElementSize = sizeof(IUnknown*);
4827                 break;
4828
4829             case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_KeyValuePair:
4830             case WinMDAdapter::RedirectedTypeIndex_System_Nullable:
4831             case WinMDAdapter::RedirectedTypeIndex_System_Uri:
4832             case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
4833             case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
4834             {
4835                 m_cbElementSize = sizeof(IInspectable *);
4836                 break;
4837             }
4838
4839             default:
4840             {
4841                 if (pMT->IsValueType())
4842                 {
4843                     // other redirected structs are blittable and don't need special marshaling
4844                     m_vtElement = VTHACK_BLITTABLERECORD;
4845                     m_cbElementSize = pMT->GetNativeSize();
4846                 }
4847                 else
4848                 {
4849                     // redirected interfaces should be treated as interface pointers
4850                     _ASSERTE(pMT->IsInterface());
4851                     m_vtElement = VTHACK_INSPECTABLE;
4852                     m_cbElementSize = sizeof(IInspectable *);
4853                 }
4854                 break;
4855             }
4856         }
4857     }
4858     else if (pMT->IsBlittable() || pMT->IsTruePrimitive() || pMT->IsEnum())
4859     {
4860         m_vtElement = VTHACK_BLITTABLERECORD;
4861
4862         CorElementType elemType = pMT->GetInternalCorElementType();
4863         if (CorTypeInfo::IsPrimitiveType(elemType))
4864         {
4865             // .NET and WinRT primitives have the same size
4866             m_cbElementSize = CorTypeInfo::Size(elemType);
4867         }
4868         else
4869         {
4870             m_cbElementSize = pMT->GetNativeSize();
4871         }
4872     }
4873     else if (pMT->IsValueType())
4874     {
4875         m_vtElement = VTHACK_NONBLITTABLERECORD;
4876         m_cbElementSize = pMT->GetNativeSize();
4877     }
4878     else
4879     {
4880         m_vtElement = VTHACK_INSPECTABLE;
4881         m_cbElementSize = sizeof(IInspectable *);
4882     }
4883
4884 LExit:;
4885 }
4886 #endif // FEATURE_COMINTEROP
4887
4888 void ArrayMarshalInfo::InitElementInfo(CorNativeType arrayNativeType, MarshalInfo::MarshalScenario ms, TypeHandle thElement, CorNativeType ntElement, BOOL isAnsi)
4889 {
4890     CONTRACT_VOID
4891     {
4892         STANDARD_VM_CHECK;
4893         PRECONDITION(!thElement.IsNull());
4894         POSTCONDITION(!IsValid() || !m_thElement.IsNull());
4895     }
4896     CONTRACT_END;
4897
4898     CorElementType etElement = ELEMENT_TYPE_END;    
4899     
4900     //
4901     // IMPORTANT: The error resource IDs used in this function must not contain any placeholders!
4902     // 
4903     // Also please maintain the standard of using IDS_EE_BADMARSHAL_XXX when defining new error
4904     // message resource IDs.
4905     //
4906
4907     if (thElement.IsArray())
4908         ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_NESTEDARRAY);
4909
4910     m_thElement = thElement;
4911
4912     if (m_thElement.IsPointer())
4913     {
4914         m_flags = (ArrayMarshalInfoFlags)(m_flags | amiIsPtr);
4915         m_thElement = ((ParamTypeDesc*)m_thElement.AsTypeDesc())->GetModifiedType();
4916     }
4917     
4918     etElement = m_thElement.GetSignatureCorElementType();
4919
4920     if (IsAMIPtr(m_flags) && (etElement > ELEMENT_TYPE_R8))
4921     {
4922         ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_UNSUPPORTED_SIG);        
4923     }
4924
4925     if (etElement == ELEMENT_TYPE_CHAR)
4926     {
4927         switch (ntElement)
4928         {
4929             case NATIVE_TYPE_I1: //fallthru
4930             case NATIVE_TYPE_U1:
4931                 m_vtElement = VTHACK_ANSICHAR;
4932                 break;
4933
4934             case NATIVE_TYPE_I2: //fallthru
4935             case NATIVE_TYPE_U2:
4936                 m_vtElement = VT_UI2;
4937                 break;
4938
4939             // Compat: If the native type doesn't make sense, we need to ignore it and not report an error.
4940             case NATIVE_TYPE_DEFAULT: //fallthru
4941             default:
4942 #ifdef FEATURE_COMINTEROP                
4943                 if (ms == MarshalInfo::MARSHAL_SCENARIO_COMINTEROP)
4944                     m_vtElement = VT_UI2;
4945                 else
4946 #endif // FEATURE_COMINTEROP
4947                     m_vtElement = isAnsi ? VTHACK_ANSICHAR : VT_UI2;                    
4948         }
4949     }
4950     else if (etElement == ELEMENT_TYPE_BOOLEAN)
4951     {
4952         switch (ntElement)
4953         {
4954             case NATIVE_TYPE_BOOLEAN:
4955                 m_vtElement = VTHACK_WINBOOL;
4956                 break;
4957
4958 #ifdef FEATURE_COMINTEROP
4959             case NATIVE_TYPE_VARIANTBOOL:
4960                 m_vtElement = VT_BOOL;
4961                 break;
4962 #endif // FEATURE_COMINTEROP
4963
4964             case NATIVE_TYPE_I1 :
4965             case NATIVE_TYPE_U1 :
4966                 m_vtElement = VTHACK_CBOOL;
4967                 break;
4968                 
4969             // Compat: if the native type doesn't make sense, we need to ignore it and not report an error.
4970             case NATIVE_TYPE_DEFAULT: //fallthru
4971             default:
4972 #ifdef FEATURE_COMINTEROP
4973                 if (ms == MarshalInfo::MARSHAL_SCENARIO_COMINTEROP ||
4974                     arrayNativeType == NATIVE_TYPE_SAFEARRAY)
4975                 {
4976                     m_vtElement = VT_BOOL;            
4977                 }
4978                 else
4979 #endif // FEATURE_COMINTEROP
4980                 {
4981                     m_vtElement = VTHACK_WINBOOL;
4982                 }
4983                 break;
4984         }                
4985     }
4986     else if (etElement == ELEMENT_TYPE_I)
4987     {
4988         m_vtElement = static_cast<VARTYPE>((GetPointerSize() == 4) ? VT_I4 : VT_I8);
4989     }
4990     else if (etElement == ELEMENT_TYPE_U)
4991     {
4992         m_vtElement = static_cast<VARTYPE>((GetPointerSize() == 4) ? VT_UI4 : VT_UI8);
4993     }
4994     else if (etElement <= ELEMENT_TYPE_R8)
4995     {
4996         static const BYTE map [] =
4997         {
4998             VT_NULL,    // ELEMENT_TYPE_END
4999             VT_VOID,    // ELEMENT_TYPE_VOID
5000             VT_NULL,    // ELEMENT_TYPE_BOOLEAN
5001             VT_NULL,    // ELEMENT_TYPE_CHAR
5002             VT_I1,      // ELEMENT_TYPE_I1
5003             VT_UI1,     // ELEMENT_TYPE_U1
5004             VT_I2,      // ELEMENT_TYPE_I2
5005             VT_UI2,     // ELEMENT_TYPE_U2
5006             VT_I4,      // ELEMENT_TYPE_I4
5007             VT_UI4,     // ELEMENT_TYPE_U4
5008             VT_I8,      // ELEMENT_TYPE_I8
5009             VT_UI8,     // ELEMENT_TYPE_U8
5010             VT_R4,      // ELEMENT_TYPE_R4
5011             VT_R8       // ELEMENT_TYPE_R8
5012
5013         };
5014
5015         _ASSERTE(map[etElement] != VT_NULL);        
5016         m_vtElement = map[etElement];
5017     }
5018     else
5019     {
5020         if (m_thElement == TypeHandle(g_pStringClass))
5021         {           
5022             switch (ntElement)
5023             {
5024                 case NATIVE_TYPE_DEFAULT:
5025 #ifdef FEATURE_COMINTEROP
5026                     if (arrayNativeType == NATIVE_TYPE_SAFEARRAY || ms == MarshalInfo::MARSHAL_SCENARIO_COMINTEROP)
5027                     {
5028                         m_vtElement = VT_BSTR;
5029                     }
5030                     else
5031 #endif // FEATURE_COMINTEROP
5032                     {
5033                         m_vtElement = static_cast<VARTYPE>(isAnsi ? VT_LPSTR : VT_LPWSTR);
5034                     }
5035                     break;
5036                 case NATIVE_TYPE_BSTR:
5037                     m_vtElement = VT_BSTR;
5038                     break;
5039                 case NATIVE_TYPE_LPSTR:
5040                     m_vtElement = VT_LPSTR;
5041                     break;
5042                 case NATIVE_TYPE_LPWSTR:
5043                     m_vtElement = VT_LPWSTR;
5044                     break;
5045                 case NATIVE_TYPE_LPTSTR:
5046                 {
5047 #ifdef FEATURE_COMINTEROP
5048                     if (ms == MarshalInfo::MARSHAL_SCENARIO_COMINTEROP || IsAMIExport(m_flags))
5049                     {
5050                         // We disallow NATIVE_TYPE_LPTSTR for COM or if we are exporting. 
5051                         ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHALPARAM_NO_LPTSTR);
5052                     }
5053                     else
5054 #endif // FEATURE_COMINTEROP
5055                     {
5056                         // We no longer support Win9x so LPTSTR always maps to a Unicode string.
5057                         m_vtElement = VT_LPWSTR;
5058                     }
5059                     break;
5060                 }
5061
5062                 default:
5063                     ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_STRINGARRAY);
5064             }
5065         }
5066         else if (m_thElement == TypeHandle(g_pObjectClass))
5067         {
5068 #ifdef FEATURE_COMINTEROP
5069             switch(ntElement)
5070             {
5071                 case NATIVE_TYPE_DEFAULT:
5072                     if (ms == MarshalInfo::MARSHAL_SCENARIO_FIELD)
5073                         m_vtElement = VT_UNKNOWN;
5074                     else
5075                         m_vtElement = VT_VARIANT;
5076                     break;
5077                     
5078                 case NATIVE_TYPE_STRUCT:
5079                     m_vtElement = VT_VARIANT;
5080                     break;
5081
5082                 case NATIVE_TYPE_INTF:
5083                 case NATIVE_TYPE_IUNKNOWN:
5084                     m_vtElement = VT_UNKNOWN;
5085                     break;
5086
5087                 case NATIVE_TYPE_IDISPATCH:
5088                     m_vtElement = VT_DISPATCH;
5089                     break;
5090
5091                 default:
5092                     ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_OBJECTARRAY);
5093             }
5094
5095 #else // FEATURE_COMINTEROP
5096             switch (ntElement)
5097             {
5098                 case NATIVE_TYPE_IUNKNOWN:
5099                     m_vtElement = VT_UNKNOWN;
5100                     break;
5101
5102                 default:
5103                     ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_UNSUPPORTED_SIG);
5104             }
5105 #endif // FEATURE_COMINTEROP
5106         }
5107         else if (m_thElement.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__SAFE_HANDLE))))
5108         {
5109             // Array's of SAFEHANDLEs are not supported.
5110             ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_SAFEHANDLEARRAY);
5111         }
5112         else if (m_thElement.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__CRITICAL_HANDLE))))
5113         {
5114             // Array's of CRITICALHANDLEs are not supported.
5115             ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_CRITICALHANDLEARRAY);
5116         }
5117         else if (etElement == ELEMENT_TYPE_VALUETYPE) 
5118         {
5119             if (m_thElement == TypeHandle(MscorlibBinder::GetClass(CLASS__DATE_TIME)))
5120             {
5121                 if (ntElement == NATIVE_TYPE_STRUCT || ntElement == NATIVE_TYPE_DEFAULT)
5122                     m_vtElement = VT_DATE;
5123                 else
5124                     ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_DATETIMEARRAY);
5125             }
5126             else if (m_thElement == TypeHandle(MscorlibBinder::GetClass(CLASS__DECIMAL)))
5127             {
5128                 if (ntElement == NATIVE_TYPE_STRUCT || ntElement == NATIVE_TYPE_DEFAULT)
5129                     m_vtElement = VT_DECIMAL;
5130 #ifdef FEATURE_COMINTEROP               
5131                 else if (ntElement == NATIVE_TYPE_CURRENCY)
5132                     m_vtElement = VT_CY;
5133 #endif // FEATURE_COMINTEROP
5134                 else
5135                     ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_DECIMALARRAY);                
5136             }
5137             else
5138             {
5139                 // When exporting, we need to handle enums specially.
5140                 if (IsAMIExport(m_flags) && m_thElement.IsEnum())
5141                 {
5142                     // Get the element type of the underlying type.
5143                     CorElementType et = m_thElement.GetInternalCorElementType();
5144                     
5145                     // If it is not a 32-bit type, convert as the underlying type.
5146                     if ((et == ELEMENT_TYPE_I4) || (et == ELEMENT_TYPE_U4))
5147                         m_vtElement = VT_RECORD;             
5148                     else
5149                         m_vtElement = OleVariant::GetVarTypeForTypeHandle(m_thElement);
5150                 }             
5151                 else
5152                 {                   
5153                     m_vtElement = OleVariant::GetVarTypeForTypeHandle(m_thElement);
5154                 }
5155             }
5156         }
5157 #ifdef FEATURE_COMINTEROP
5158         else if (m_thElement == TypeHandle(MscorlibBinder::GetClass(CLASS__ERROR_WRAPPER)))
5159         {
5160             m_vtElement = VT_ERROR;
5161         }
5162 #endif
5163         else
5164         {
5165 #ifdef FEATURE_COMINTEROP
5166
5167             // Compat: Even if the classes have layout, we still convert them to interface pointers.
5168
5169             ItfMarshalInfo itfInfo;
5170             MarshalInfo::GetItfMarshalInfo(m_thElement, TypeHandle(), FALSE, FALSE, ms, &itfInfo);
5171
5172             // Compat: We must always do VT_UNKNOWN marshaling for parameters, even if the interface is marked late-bound.
5173             if (ms == MarshalInfo::MARSHAL_SCENARIO_FIELD)
5174                 m_vtElement = static_cast<VARTYPE>(!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF) ? VT_DISPATCH : VT_UNKNOWN);
5175             else
5176                 m_vtElement = VT_UNKNOWN;
5177             
5178             m_thElement = itfInfo.thItf.IsNull() ? TypeHandle(g_pObjectClass) : itfInfo.thItf;
5179             m_thInterfaceArrayElementClass = itfInfo.thClass;
5180             
5181 #else // FEATURE_COMINTEROP
5182             ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_UNSUPPORTED_SIG);
5183 #endif // FEATURE_COMINTEROP
5184         }
5185     }
5186
5187    // Avoid throwing exceptions for any managed structs that have layouts and have types of fields that gets default to those banned types by default 
5188    // We don't know if they will be passed to native code anyway, and the right place to make the check is in the marshallers
5189    if (AppX::IsAppXProcess() && ms != MarshalInfo::MARSHAL_SCENARIO_FIELD)
5190     {
5191        bool set_error = false;
5192        UINT m_resID = 0;  
5193        switch (m_vtElement)
5194        {
5195            case VT_DISPATCH:
5196                  m_resID = IDS_EE_BADMARSHAL_TYPE_IDISPATCH ;
5197                  set_error = true;
5198                 break;
5199        }
5200         if (set_error)
5201             COMPlusThrow(kPlatformNotSupportedException, m_resID);
5202     }
5203
5204     // If we are exporting, we need to substitute the VTHACK_* VARTYPE with the actual
5205     // types as expressed in the type library.
5206     if (IsAMIExport(m_flags))
5207     {
5208         if (m_vtElement == VTHACK_ANSICHAR)
5209             m_vtElement = VT_UI1;
5210         else if (m_vtElement == VTHACK_WINBOOL)
5211             m_vtElement = VT_I4;
5212                 else if (m_vtElement == VTHACK_CBOOL)
5213                     m_vtElement = VT_UI1;
5214     }
5215
5216 LExit:;
5217     
5218     RETURN;
5219 }
5220
5221 bool IsUnsupportedTypedrefReturn(MetaSig& msig)
5222 {
5223     WRAPPER_NO_CONTRACT;
5224
5225     return msig.GetReturnTypeNormalized() == ELEMENT_TYPE_TYPEDBYREF;
5226 }
5227
5228 #ifndef CROSSGEN_COMPILE
5229
5230 #include "stubhelpers.h"
5231 FCIMPL3(void*, StubHelpers::CreateCustomMarshalerHelper, 
5232             MethodDesc* pMD,
5233             mdToken paramToken,
5234             TypeHandle hndManagedType)
5235 {
5236     FCALL_CONTRACT;
5237
5238     CustomMarshalerHelper* pCMHelper = NULL;
5239
5240     HELPER_METHOD_FRAME_BEGIN_RET_0();
5241     
5242     Module* pModule = pMD->GetModule();
5243     Assembly* pAssembly = pModule->GetAssembly();
5244     
5245
5246 #ifdef FEATURE_COMINTEROP
5247     if (!hndManagedType.IsTypeDesc() &&
5248         IsTypeRefOrDef(g_CollectionsEnumeratorClassName, hndManagedType.GetModule(), hndManagedType.GetCl()))
5249     {
5250         pCMHelper = SetupCustomMarshalerHelper(ENUMERATOR_TO_ENUM_VARIANT_CM_NAME, 
5251                                                ENUMERATOR_TO_ENUM_VARIANT_CM_NAME_LEN,
5252                                                ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE, 
5253                                                ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE_LEN, 
5254                                                pAssembly, hndManagedType);
5255     }
5256     else
5257 #endif // FEATURE_COMINTEROP
5258     {
5259         //
5260         // Retrieve the native type for the current parameter.
5261         //
5262
5263         BOOL result;
5264         NativeTypeParamInfo ParamInfo;
5265         result = ParseNativeTypeInfo(paramToken, pModule->GetMDImport(), &ParamInfo);
5266
5267         //
5268         // this should all have been done at stub creation time
5269         //
5270         CONSISTENCY_CHECK(result != 0);
5271         CONSISTENCY_CHECK(ParamInfo.m_NativeType == NATIVE_TYPE_CUSTOMMARSHALER);
5272         
5273         // Set up the custom marshaler info.
5274         pCMHelper = SetupCustomMarshalerHelper(ParamInfo.m_strCMMarshalerTypeName, 
5275                                                 ParamInfo.m_cCMMarshalerTypeNameBytes,
5276                                                 ParamInfo.m_strCMCookie, 
5277                                                 ParamInfo.m_cCMCookieStrBytes,
5278                                                 pAssembly,
5279                                                 hndManagedType);
5280     }
5281
5282     HELPER_METHOD_FRAME_END();
5283
5284     return (void*)pCMHelper;
5285 }
5286 FCIMPLEND
5287
5288 #endif // CROSSGEN_COMPILE