Port CustomMarshalers.dll to C# and .NET Core (#21343)
[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 = GetThread()->GetDomain()->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(BaseDomain *pDomain, LoaderHeap *pHeap, CrstBase *pCrst) :
1076     m_pHeap(pHeap),
1077     m_pDomain(pDomain)
1078 {
1079     CONTRACTL
1080     {
1081         NOTHROW;
1082         GC_NOTRIGGER;
1083         MODE_ANY;
1084     }
1085     CONTRACTL_END;
1086     
1087     LockOwner lock = {pCrst, IsOwnerOfCrst};
1088 #ifndef CROSSGEN_COMPILE
1089     m_CMHelperHashtable.Init(INITIAL_NUM_CMHELPER_HASHTABLE_BUCKETS, &lock);
1090     m_SharedCMHelperToCMInfoMap.Init(INITIAL_NUM_CMINFO_HASHTABLE_BUCKETS, &lock);
1091 #endif // CROSSGEN_COMPILE
1092 }
1093
1094
1095 EEMarshalingData::~EEMarshalingData()
1096 {
1097     WRAPPER_NO_CONTRACT;
1098     
1099     CustomMarshalerInfo *pCMInfo;
1100
1101     // <TODO>@TODO(DM): Remove the linked list of CMInfo's and instead hang the OBJECTHANDLE 
1102     // contained inside the CMInfo off the AppDomain directly. The AppDomain can have
1103     // a list of tasks to do when it gets teared down and we could leverage that
1104     // to release the object handles.</TODO>
1105
1106     // Walk through the linked list and delete all the custom marshaler info's.
1107     while ((pCMInfo = m_pCMInfoList.RemoveHead()) != NULL)
1108         delete pCMInfo;
1109
1110 #ifdef FEATURE_COMINTEROP
1111     if (m_pOleColorInfo)
1112     {
1113         delete m_pOleColorInfo;
1114         m_pOleColorInfo = NULL;
1115     }
1116     
1117     if (m_pUriInfo)
1118     {
1119         delete m_pUriInfo;
1120         m_pUriInfo = NULL;
1121     }
1122     
1123     if (m_pEventArgsInfo)
1124     {
1125         delete m_pEventArgsInfo;
1126         m_pEventArgsInfo = NULL;
1127     }    
1128 #endif
1129 }
1130
1131
1132 void *EEMarshalingData::operator new(size_t size, LoaderHeap *pHeap)
1133 {
1134     CONTRACT (void*)
1135     {
1136         THROWS;
1137         GC_NOTRIGGER;
1138         MODE_ANY;
1139         INJECT_FAULT(COMPlusThrowOM());
1140         PRECONDITION(CheckPointer(pHeap));
1141         POSTCONDITION(CheckPointer(RETVAL));
1142     }
1143     CONTRACT_END;
1144
1145     void* mem = pHeap->AllocMem(S_SIZE_T(sizeof(EEMarshalingData)));
1146
1147     RETURN mem;
1148 }
1149
1150
1151 void EEMarshalingData::operator delete(void *pMem)
1152 {
1153     LIMITED_METHOD_CONTRACT;
1154     // Instances of this class are always allocated on the loader heap so
1155     // the delete operator has nothing to do.
1156 }
1157
1158 #ifndef CROSSGEN_COMPILE
1159
1160 CustomMarshalerHelper *EEMarshalingData::GetCustomMarshalerHelper(Assembly *pAssembly, TypeHandle hndManagedType, LPCUTF8 strMarshalerTypeName, DWORD cMarshalerTypeNameBytes, LPCUTF8 strCookie, DWORD cCookieStrBytes)
1161 {
1162     CONTRACT (CustomMarshalerHelper*)
1163     {
1164         THROWS;
1165         GC_TRIGGERS;
1166         MODE_ANY;
1167         INJECT_FAULT(COMPlusThrowOM());
1168         PRECONDITION(CheckPointer(pAssembly));
1169         POSTCONDITION(CheckPointer(RETVAL));
1170     }
1171     CONTRACT_END;
1172
1173     CustomMarshalerHelper *pCMHelper = NULL;
1174     CustomMarshalerHelper* pNewCMHelper = NULL;
1175     NewHolder<CustomMarshalerInfo> pNewCMInfo(NULL);
1176     
1177     TypeHandle hndCustomMarshalerType;
1178
1179     // Create the key that will be used to lookup in the hashtable.
1180     EECMHelperHashtableKey Key(cMarshalerTypeNameBytes, strMarshalerTypeName, cCookieStrBytes, strCookie, hndManagedType.GetInstantiation());
1181
1182     // Lookup the custom marshaler helper in the hashtable.
1183     if (m_CMHelperHashtable.GetValue(&Key, (HashDatum*)&pCMHelper))
1184         RETURN pCMHelper;
1185
1186     {
1187         GCX_COOP();
1188
1189         // Validate the arguments.
1190         _ASSERTE(strMarshalerTypeName && strCookie && !hndManagedType.IsNull());
1191
1192         // Append a NULL terminator to the marshaler type name.
1193         SString strCMMarshalerTypeName(SString::Utf8, strMarshalerTypeName, cMarshalerTypeNameBytes);
1194
1195         // Load the custom marshaler class. 
1196         BOOL fNameIsAsmQualified = FALSE;
1197         hndCustomMarshalerType = TypeName::GetTypeUsingCASearchRules(strCMMarshalerTypeName.GetUTF8NoConvert(), pAssembly, &fNameIsAsmQualified);
1198         
1199         if (hndCustomMarshalerType.IsGenericTypeDefinition())
1200         {
1201             // Instantiate generic custom marshalers using the instantiation of the type being marshaled.
1202             hndCustomMarshalerType = hndCustomMarshalerType.Instantiate(hndManagedType.GetInstantiation());
1203         }
1204
1205         // Set the assembly to null to indicate that the custom marshaler name is assembly
1206         // qualified.        
1207         if (fNameIsAsmQualified)
1208             pAssembly = NULL;
1209
1210
1211         // Create the custom marshaler info in the specified heap.
1212         pNewCMInfo = new (m_pHeap) CustomMarshalerInfo(m_pDomain, hndCustomMarshalerType, hndManagedType, strCookie, cCookieStrBytes);
1213
1214         // Create the custom marshaler helper in the specified heap.
1215         pNewCMHelper = new (m_pHeap) NonSharedCustomMarshalerHelper(pNewCMInfo);
1216     }
1217
1218     // Take the app domain lock before we insert the custom marshaler info into the hashtable.
1219     {
1220         BaseDomain::LockHolder lh(m_pDomain);
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_pDomain, 
1281                                                    hndCustomMarshalerType, 
1282                                                    pSharedCMHelper->GetManagedType(), 
1283                                                    pSharedCMHelper->GetCookieString(), 
1284                                                    pSharedCMHelper->GetCookieStringByteCount());
1285
1286     {
1287         // Take the app domain lock before we insert the custom marshaler info into the hashtable.
1288         BaseDomain::LockHolder lh(m_pDomain);
1289
1290         // Verify that the custom marshaler info has not already been added by another thread.
1291         if (m_SharedCMHelperToCMInfoMap.GetValue(pSharedCMHelper, (HashDatum*)&pCMInfo))
1292         {
1293             RETURN pCMInfo;
1294         }
1295
1296         // Add the custom marshaler helper to the hash table.
1297         m_SharedCMHelperToCMInfoMap.InsertValue(pSharedCMHelper, pNewCMInfo, FALSE);
1298
1299         // Add the custom marshaler into the linked list.
1300         m_pCMInfoList.InsertHead(pNewCMInfo);
1301
1302         // Release the lock and return the custom marshaler info.
1303     }
1304
1305     pNewCMInfo.SuppressRelease();
1306     RETURN pNewCMInfo;
1307 }
1308 #endif // CROSSGEN_COMPILE
1309
1310 #ifdef FEATURE_COMINTEROP
1311 UriMarshalingInfo *EEMarshalingData::GetUriMarshalingInfo()
1312 {
1313     CONTRACT (UriMarshalingInfo*)
1314     {
1315         THROWS;
1316         GC_TRIGGERS;
1317         MODE_ANY;
1318         INJECT_FAULT(COMPlusThrowOM());
1319         POSTCONDITION(CheckPointer(RETVAL));
1320     }
1321     CONTRACT_END;
1322        
1323     if (m_pUriInfo == NULL)
1324     {
1325         UriMarshalingInfo *pUriInfo = new (m_pHeap) UriMarshalingInfo();
1326
1327         if (InterlockedCompareExchangeT(&m_pUriInfo, pUriInfo, NULL) != NULL)
1328         {
1329             // Another thread beat us to it. Delete on UriMarshalingInfo is an empty operation
1330             // which is OK, since the possible leak is rare, small, and constant. This is the same
1331             // pattern as in code:GetCustomMarshalerInfo.
1332             delete pUriInfo;
1333         }
1334     }
1335
1336     RETURN m_pUriInfo;
1337 }
1338
1339 EventArgsMarshalingInfo *EEMarshalingData::GetEventArgsMarshalingInfo()
1340 {
1341     CONTRACT (EventArgsMarshalingInfo*)
1342     {
1343         THROWS;
1344         GC_TRIGGERS;
1345         MODE_ANY;
1346         INJECT_FAULT(COMPlusThrowOM());
1347         POSTCONDITION(CheckPointer(RETVAL));
1348     }
1349     CONTRACT_END;
1350        
1351     if (m_pEventArgsInfo == NULL)
1352     {
1353         EventArgsMarshalingInfo *pEventArgsInfo = new (m_pHeap) EventArgsMarshalingInfo();
1354
1355         if (InterlockedCompareExchangeT(&m_pEventArgsInfo, pEventArgsInfo, NULL) != NULL)
1356         {
1357             // Another thread beat us to it. Delete on EventArgsMarshalingInfo is an empty operation
1358             // which is OK, since the possible leak is rare, small, and constant. This is the same
1359             // pattern as in code:GetCustomMarshalerInfo.
1360             delete pEventArgsInfo;
1361         }
1362     }
1363
1364     RETURN m_pEventArgsInfo;
1365 }
1366
1367 OleColorMarshalingInfo *EEMarshalingData::GetOleColorMarshalingInfo()
1368 {
1369     CONTRACT (OleColorMarshalingInfo*)
1370     {
1371         THROWS;
1372         GC_TRIGGERS;
1373         MODE_ANY;
1374         INJECT_FAULT(COMPlusThrowOM());
1375         POSTCONDITION(CheckPointer(RETVAL));
1376     }
1377     CONTRACT_END;
1378        
1379     if (m_pOleColorInfo == NULL)
1380     {
1381         OleColorMarshalingInfo *pOleColorInfo = new (m_pHeap) OleColorMarshalingInfo();
1382
1383     if (InterlockedCompareExchangeT(&m_pOleColorInfo, pOleColorInfo, NULL) != NULL)
1384         {
1385             // Another thread beat us to it. Delete on OleColorMarshalingInfo is an empty operation
1386             // which is OK, since the possible leak is rare, small, and constant. This is the same
1387             // pattern as in code:GetCustomMarshalerInfo.
1388             delete pOleColorInfo;
1389         }
1390     }
1391
1392     RETURN m_pOleColorInfo;
1393 }
1394 #endif // FEATURE_COMINTEROP
1395
1396 //==========================================================================
1397 // Constructs MarshalInfo. 
1398 //==========================================================================
1399 #ifdef _PREFAST_
1400 #pragma warning(push)
1401 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
1402 #endif
1403 MarshalInfo::MarshalInfo(Module* pModule,
1404                          SigPointer sig,
1405                          const SigTypeContext *pTypeContext,
1406                          mdToken token,
1407                          MarshalScenario ms,
1408                          CorNativeLinkType nlType,
1409                          CorNativeLinkFlags nlFlags,
1410                          BOOL isParam,
1411                          UINT paramidx,   // parameter # for use in error messages (ignored if not parameter)                         
1412                          UINT numArgs,    // number of arguments
1413                          BOOL BestFit,
1414                          BOOL ThrowOnUnmappableChar,
1415                          BOOL fEmitsIL,
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     m_BestFit                       = BestFit;
1443     m_ThrowOnUnmappableChar         = ThrowOnUnmappableChar;
1444     m_ms                            = ms;
1445     m_fAnsi                         = (ms == MARSHAL_SCENARIO_NDIRECT) && (nlType == nltAnsi);
1446     m_managedArgSize                = 0;
1447     m_nativeArgSize                 = 0;
1448     m_pCMHelper                     = NULL;
1449     m_CMVt                          = VT_EMPTY;
1450     m_args.m_pMarshalInfo           = this;
1451     m_args.m_pMT                    = NULL;
1452     m_pModule                       = pModule;
1453     CorElementType mtype            = ELEMENT_TYPE_END;
1454     CorElementType corElemType      = ELEMENT_TYPE_END;
1455     m_pMT                           = NULL;
1456     m_pMD                           = pMD;
1457
1458 #ifdef FEATURE_COMINTEROP
1459     m_fDispItf                      = FALSE;
1460     m_fInspItf                      = FALSE;
1461     m_fErrorNativeType              = FALSE;
1462     m_hiddenLengthParamIndex        = (UINT16)-1;
1463     m_dwHiddenLengthManagedHomeLocal= 0xFFFFFFFF;
1464     m_dwHiddenLengthNativeHomeLocal = 0xFFFFFFFF;
1465
1466     m_pDefaultItfMT                 = NULL;
1467 #endif // FEATURE_COMINTEROP
1468
1469
1470 #ifdef _DEBUG
1471
1472     CHAR achDbgContext[DEBUG_CONTEXT_STR_LEN] = "";
1473     if (!pDebugName)
1474     {
1475         strncpy_s(achDbgContext, COUNTOF(achDbgContext), "<Unknown>", _TRUNCATE);
1476     }
1477     else
1478     {
1479         strncat_s(achDbgContext, COUNTOF(achDbgContext), pDebugClassName, _TRUNCATE);
1480         strncat_s(achDbgContext, COUNTOF(achDbgContext), NAMESPACE_SEPARATOR_STR, _TRUNCATE);
1481         strncat_s(achDbgContext, COUNTOF(achDbgContext), pDebugName, _TRUNCATE);
1482         strncat_s(achDbgContext, COUNTOF(achDbgContext), " ", _TRUNCATE);
1483         switch (argidx)
1484         {
1485             case (UINT)-1:
1486                 strncat_s(achDbgContext, COUNTOF(achDbgContext), "field", _TRUNCATE);
1487                 break;
1488             case 0:
1489                 strncat_s(achDbgContext, COUNTOF(achDbgContext), "return value", _TRUNCATE);
1490                 break;
1491             default:
1492             {
1493                 char buf[30];
1494                 sprintf_s(buf, COUNTOF(buf), "param #%lu", (ULONG)argidx);
1495                 strncat_s(achDbgContext, COUNTOF(achDbgContext), buf, _TRUNCATE);
1496             }
1497         }
1498     }
1499
1500     m_strDebugMethName = pDebugName;
1501     m_strDebugClassName = pDebugClassName;
1502     m_iArg = argidx;
1503
1504     m_in = m_out = FALSE;
1505     m_byref = TRUE;
1506 #endif
1507
1508
1509
1510     // Retrieve the native type for the current parameter.
1511     if (!ParseNativeTypeInfo(token, pModule->GetMDImport(), &ParamInfo))
1512     {
1513         IfFailGoto(E_FAIL, lFail);
1514     }
1515    
1516     nativeType = ParamInfo.m_NativeType;
1517     corElemType = sig.PeekElemTypeNormalized(pModule, pTypeContext); 
1518     mtype       = corElemType;
1519
1520 #ifdef FEATURE_COMINTEROP
1521     if (IsWinRTScenario() && nativeType != NATIVE_TYPE_DEFAULT)
1522     {
1523         // Do not allow any MarshalAs in WinRT scenarios - marshaling is fully described by the parameter type.
1524         m_type = MARSHAL_TYPE_UNKNOWN; 
1525         m_resID = IDS_EE_BADMARSHAL_WINRT_MARSHAL_AS;
1526         IfFailGoto(E_FAIL, lFail);
1527     }
1528 #endif // FEATURE_COMINTEROP
1529
1530     // Make sure SizeParamIndex < numArgs when marshalling native arrays
1531     if (nativeType == NATIVE_TYPE_ARRAY && ParamInfo.m_SizeIsSpecified)
1532     {
1533         if (ParamInfo.m_Multiplier > 0 && ParamInfo.m_CountParamIdx >= numArgs)
1534         {        
1535             // Do not throw exception here. 
1536             // We'll use EmitOrThrowInteropException to throw exception in non-COM interop
1537             // and emit exception throwing code directly in STUB in COM interop
1538             m_type = MARSHAL_TYPE_UNKNOWN; 
1539             m_resID = IDS_EE_SIZECONTROLOUTOFRANGE;
1540             IfFailGoto(E_FAIL, lFail);
1541         }
1542     }
1543
1544     // Parse ET_BYREF signature
1545     if (mtype == ELEMENT_TYPE_BYREF)
1546     {
1547         m_byref = TRUE;
1548         SigPointer sigtmp = sig;
1549         IfFailGoto(sig.GetElemType(NULL), lFail);
1550         mtype = sig.PeekElemTypeNormalized(pModule, pTypeContext); 
1551
1552     }
1553     else
1554     {
1555         m_byref = FALSE;
1556     }
1557
1558     // Check for valid ET_PTR signature
1559     if (mtype == ELEMENT_TYPE_PTR)
1560     {
1561 #ifdef FEATURE_COMINTEROP
1562         // WinRT does not support ET_PTR
1563         if (IsWinRTScenario())
1564         {
1565             m_type = MARSHAL_TYPE_UNKNOWN; 
1566             m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
1567             IfFailGoto(E_FAIL, lFail);
1568         }
1569 #endif // FEATURE_COMINTEROP
1570
1571         SigPointer sigtmp = sig;
1572         IfFailGoto(sigtmp.GetElemType(NULL), lFail);
1573
1574         // Peek closed elem type here to prevent ELEMENT_TYPE_VALUETYPE turning into a primitive. 
1575         CorElementType mtype2 = sigtmp.PeekElemTypeClosed(pModule, pTypeContext);
1576
1577         if (mtype2 == ELEMENT_TYPE_VALUETYPE) 
1578         {
1579
1580             TypeHandle th = sigtmp.GetTypeHandleThrowing(pModule, pTypeContext);
1581             _ASSERTE(!th.IsNull());
1582
1583             // We want to leave out enums as they surely don't have copy constructors
1584             // plus they are not marked as blittable.
1585             if (!th.IsEnum())
1586             {
1587                 // It should be blittable
1588                 if (!th.IsBlittable())
1589                 {
1590                     m_resID = IDS_EE_BADMARSHAL_PTRNONBLITTABLE;
1591                     IfFailGoto(E_FAIL, lFail);
1592                 }
1593
1594             }
1595         }
1596         else
1597         {
1598             if (!(mtype2 != ELEMENT_TYPE_CLASS &&
1599                   mtype2 != ELEMENT_TYPE_STRING &&
1600                   mtype2 != ELEMENT_TYPE_OBJECT &&
1601                   mtype2 != ELEMENT_TYPE_SZARRAY))
1602             {
1603                 m_resID = IDS_EE_BADMARSHAL_PTRSUBTYPE;
1604                 IfFailGoto(E_FAIL, lFail);
1605             }
1606         }
1607     }
1608
1609
1610     // System primitive types (System.Int32, et.al.) will be marshaled as expected
1611     // because the mtype CorElementType is normalized (e.g. ELEMENT_TYPE_I4).
1612 #ifdef _TARGET_X86_
1613     // We however need to detect if such a normalization occurred for non-system
1614     // trivial value types, because we hold CorNativeType belonging to the original
1615     // "un-normalized" signature type. It has to be verified that all the value types
1616     // that have been normalized away have default marshaling or MarshalAs(Struct).
1617     // In addition, the nativeType must be updated with the type of the real primitive inside.
1618     // 
1619     VerifyAndAdjustNormalizedType(pModule, sig, pTypeContext, &mtype, &nativeType);
1620 #endif // _TARGET_X86_
1621
1622
1623     if (nativeType == NATIVE_TYPE_CUSTOMMARSHALER)
1624     {
1625         switch (mtype)
1626         {
1627             case ELEMENT_TYPE_VAR:
1628             case ELEMENT_TYPE_CLASS:
1629             case ELEMENT_TYPE_OBJECT:
1630                 m_CMVt = VT_UNKNOWN;
1631                 break;
1632
1633             case ELEMENT_TYPE_STRING:
1634             case ELEMENT_TYPE_SZARRAY:
1635             case ELEMENT_TYPE_ARRAY:
1636                 m_CMVt = VT_I4;
1637                 break;
1638
1639             default:    
1640                 m_resID = IDS_EE_BADMARSHAL_CUSTOMMARSHALER;
1641                 IfFailGoto(E_FAIL, lFail);
1642         }
1643
1644         // Set m_type to MARSHAL_TYPE_UNKNOWN in case SetupCustomMarshalerHelper throws.
1645         m_type = MARSHAL_TYPE_UNKNOWN; 
1646
1647         if (fLoadCustomMarshal)
1648         {
1649             // Set up the custom marshaler info.
1650             TypeHandle hndManagedType = sig.GetTypeHandleThrowing(pModule, pTypeContext);
1651
1652             if (!fEmitsIL)
1653             {
1654                 m_pCMHelper = SetupCustomMarshalerHelper(ParamInfo.m_strCMMarshalerTypeName, 
1655                                                         ParamInfo.m_cCMMarshalerTypeNameBytes,
1656                                                         ParamInfo.m_strCMCookie, 
1657                                                         ParamInfo.m_cCMCookieStrBytes,
1658                                                         pAssembly,
1659                                                         hndManagedType);
1660             }
1661             else
1662             {
1663                 m_pCMHelper = NULL;
1664                 MethodDesc* pMDforModule = pMD;
1665                 if (pMD->IsILStub())
1666                 {
1667                     pMDforModule = pMD->AsDynamicMethodDesc()->GetILStubResolver()->GetStubTargetMethodDesc();
1668                 }
1669                 m_args.rcm.m_pMD = pMDforModule;
1670                 m_args.rcm.m_paramToken = token;
1671                 m_args.rcm.m_hndManagedType = hndManagedType.AsPtr();
1672                 CONSISTENCY_CHECK(pModule == pMDforModule->GetModule());
1673             }
1674         }
1675
1676         // Specify which custom marshaler to use.
1677         m_type = MARSHAL_TYPE_REFERENCECUSTOMMARSHALER;
1678
1679         goto lExit;
1680     }
1681    
1682     switch (mtype)
1683     {
1684         case ELEMENT_TYPE_BOOLEAN:
1685             switch (nativeType)
1686             {
1687                 case NATIVE_TYPE_BOOLEAN:
1688                     m_type = MARSHAL_TYPE_WINBOOL;
1689                     break;
1690
1691 #ifdef FEATURE_COMINTEROP
1692                 case NATIVE_TYPE_VARIANTBOOL:
1693                     m_type = MARSHAL_TYPE_VTBOOL;
1694                     break;
1695 #endif // FEATURE_COMINTEROP
1696
1697                 case NATIVE_TYPE_U1:
1698                 case NATIVE_TYPE_I1:
1699                     m_type = MARSHAL_TYPE_CBOOL;
1700                     break;
1701
1702                 case NATIVE_TYPE_DEFAULT:
1703 #ifdef FEATURE_COMINTEROP
1704                     if (m_ms == MARSHAL_SCENARIO_COMINTEROP)
1705                     {
1706                         // 2-byte COM VARIANT_BOOL
1707                         m_type = MARSHAL_TYPE_VTBOOL;
1708                     }
1709                     else if (m_ms == MARSHAL_SCENARIO_WINRT)
1710                     {
1711                         // 1-byte WinRT bool
1712                         m_type = MARSHAL_TYPE_CBOOL;
1713                     }
1714                     else
1715 #endif // FEATURE_COMINTEROP
1716                     {
1717                         // 4-byte Windows BOOL
1718                         _ASSERTE(m_ms == MARSHAL_SCENARIO_NDIRECT);
1719                         m_type = MARSHAL_TYPE_WINBOOL;
1720                     }
1721                     break;
1722
1723                 default:
1724                     m_resID = IDS_EE_BADMARSHAL_BOOLEAN;
1725                     IfFailGoto(E_FAIL, lFail);
1726             }
1727             break;
1728
1729         case ELEMENT_TYPE_CHAR:
1730             switch (nativeType)
1731             {
1732                 case NATIVE_TYPE_I1: //fallthru
1733                 case NATIVE_TYPE_U1:
1734                     m_type = MARSHAL_TYPE_ANSICHAR;
1735                     break;
1736
1737                 case NATIVE_TYPE_I2: //fallthru
1738                 case NATIVE_TYPE_U2:
1739                     m_type = MARSHAL_TYPE_GENERIC_U2;
1740                     break;
1741
1742                 case NATIVE_TYPE_DEFAULT:
1743                     m_type = ( (m_ms == MARSHAL_SCENARIO_NDIRECT && m_fAnsi) ? MARSHAL_TYPE_ANSICHAR : MARSHAL_TYPE_GENERIC_U2 );
1744                     break;
1745
1746                 default:
1747                     m_resID = IDS_EE_BADMARSHAL_CHAR;
1748                     IfFailGoto(E_FAIL, lFail);
1749
1750             }
1751             break;
1752
1753         case ELEMENT_TYPE_I1:
1754             if (!(nativeType == NATIVE_TYPE_I1 || nativeType == NATIVE_TYPE_U1 || nativeType == NATIVE_TYPE_DEFAULT))
1755             {
1756                 m_resID = IDS_EE_BADMARSHAL_I1;
1757                 IfFailGoto(E_FAIL, lFail);
1758             }
1759             m_type = MARSHAL_TYPE_GENERIC_1;
1760             break;
1761
1762         case ELEMENT_TYPE_U1:
1763             if (!(nativeType == NATIVE_TYPE_U1 || nativeType == NATIVE_TYPE_I1 || nativeType == NATIVE_TYPE_DEFAULT))
1764             {
1765                 m_resID = IDS_EE_BADMARSHAL_I1;
1766                 IfFailGoto(E_FAIL, lFail);
1767             }
1768             m_type = MARSHAL_TYPE_GENERIC_U1;
1769             break;
1770
1771         case ELEMENT_TYPE_I2:
1772             if (!(nativeType == NATIVE_TYPE_I2 || nativeType == NATIVE_TYPE_U2 || nativeType == NATIVE_TYPE_DEFAULT))
1773             {
1774                 m_resID = IDS_EE_BADMARSHAL_I2;
1775                 IfFailGoto(E_FAIL, lFail);
1776             }
1777             m_type = MARSHAL_TYPE_GENERIC_2;
1778             break;
1779
1780         case ELEMENT_TYPE_U2:
1781             if (!(nativeType == NATIVE_TYPE_U2 || nativeType == NATIVE_TYPE_I2 || nativeType == NATIVE_TYPE_DEFAULT))
1782             {
1783                 m_resID = IDS_EE_BADMARSHAL_I2;
1784                 IfFailGoto(E_FAIL, lFail);
1785             }
1786             m_type = MARSHAL_TYPE_GENERIC_U2;
1787             break;
1788
1789         case ELEMENT_TYPE_I4:
1790             switch (nativeType)
1791             {
1792                 case NATIVE_TYPE_I4:
1793                 case NATIVE_TYPE_U4:
1794                 case NATIVE_TYPE_DEFAULT:
1795                     break;
1796
1797 #ifdef FEATURE_COMINTEROP
1798                 case NATIVE_TYPE_ERROR:
1799                     m_fErrorNativeType = TRUE;
1800                     break;
1801 #endif // FEATURE_COMINTEROP
1802
1803                 default:
1804                 m_resID = IDS_EE_BADMARSHAL_I4;
1805                 IfFailGoto(E_FAIL, lFail);
1806             }
1807             m_type = MARSHAL_TYPE_GENERIC_4;
1808             break;
1809
1810         case ELEMENT_TYPE_U4:
1811             switch (nativeType)
1812             {
1813                 case NATIVE_TYPE_I4:
1814                 case NATIVE_TYPE_U4:
1815                 case NATIVE_TYPE_DEFAULT:
1816                     break;
1817
1818 #ifdef FEATURE_COMINTEROP
1819                 case NATIVE_TYPE_ERROR:
1820                     m_fErrorNativeType = TRUE;
1821                     break;
1822 #endif // FEATURE_COMINTEROP
1823
1824                 default:
1825                 m_resID = IDS_EE_BADMARSHAL_I4;
1826                 IfFailGoto(E_FAIL, lFail);
1827             }
1828             m_type = MARSHAL_TYPE_GENERIC_4;
1829             break;
1830
1831         case ELEMENT_TYPE_I8:
1832             if (!(nativeType == NATIVE_TYPE_I8 || nativeType == NATIVE_TYPE_U8 || nativeType == NATIVE_TYPE_DEFAULT))
1833             {
1834                 m_resID = IDS_EE_BADMARSHAL_I8;
1835                 IfFailGoto(E_FAIL, lFail);
1836             }
1837             m_type = MARSHAL_TYPE_GENERIC_8;
1838             break;
1839
1840         case ELEMENT_TYPE_U8:
1841             if (!(nativeType == NATIVE_TYPE_U8 || nativeType == NATIVE_TYPE_I8 || nativeType == NATIVE_TYPE_DEFAULT))
1842             {
1843                 m_resID = IDS_EE_BADMARSHAL_I8;
1844                 IfFailGoto(E_FAIL, lFail);
1845             }
1846             m_type = MARSHAL_TYPE_GENERIC_8;
1847             break;
1848
1849         case ELEMENT_TYPE_I:
1850 #ifdef FEATURE_COMINTEROP
1851             if (IsWinRTScenario())
1852             {
1853                 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
1854                 IfFailGoto(E_FAIL, lFail);
1855             }
1856 #endif // FEATURE_COMINTEROP
1857
1858             if (!(nativeType == NATIVE_TYPE_INT || nativeType == NATIVE_TYPE_UINT || nativeType == NATIVE_TYPE_DEFAULT))
1859             {
1860                 m_resID = IDS_EE_BADMARSHAL_I;
1861                 IfFailGoto(E_FAIL, lFail);
1862             }
1863             m_type = (sizeof(LPVOID) == 4 ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8);
1864             break;
1865
1866         case ELEMENT_TYPE_U:
1867 #ifdef FEATURE_COMINTEROP
1868             if (IsWinRTScenario())
1869             {
1870                 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
1871                 IfFailGoto(E_FAIL, lFail);
1872             }
1873 #endif // FEATURE_COMINTEROP
1874
1875             if (!(nativeType == NATIVE_TYPE_UINT || nativeType == NATIVE_TYPE_INT || nativeType == NATIVE_TYPE_DEFAULT))
1876             {
1877                 m_resID = IDS_EE_BADMARSHAL_I;
1878                 IfFailGoto(E_FAIL, lFail);
1879             }
1880             m_type = (sizeof(LPVOID) == 4 ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8);
1881             break;
1882
1883
1884         case ELEMENT_TYPE_R4:
1885             if (!(nativeType == NATIVE_TYPE_R4 || nativeType == NATIVE_TYPE_DEFAULT))
1886             {
1887                 m_resID = IDS_EE_BADMARSHAL_R4;
1888                 IfFailGoto(E_FAIL, lFail);
1889             }
1890             m_type = MARSHAL_TYPE_FLOAT;
1891             break;
1892
1893         case ELEMENT_TYPE_R8:
1894             if (!(nativeType == NATIVE_TYPE_R8 || nativeType == NATIVE_TYPE_DEFAULT))
1895             {
1896                 m_resID = IDS_EE_BADMARSHAL_R8;
1897                 IfFailGoto(E_FAIL, lFail);
1898             }
1899             m_type = MARSHAL_TYPE_DOUBLE;
1900             break;
1901
1902         case ELEMENT_TYPE_PTR:
1903 #ifdef FEATURE_COMINTEROP
1904             _ASSERTE(!IsWinRTScenario()); // we checked for this earlier
1905 #endif // FEATURE_COMINTEROP
1906
1907             if (nativeType != NATIVE_TYPE_DEFAULT)
1908             {
1909                 m_resID = IDS_EE_BADMARSHAL_PTR;
1910                 IfFailGoto(E_FAIL, lFail);
1911             }
1912             m_type = ( (sizeof(void*)==4) ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8 );
1913             break;
1914
1915         case ELEMENT_TYPE_FNPTR:
1916 #ifdef FEATURE_COMINTEROP
1917             if (IsWinRTScenario())
1918             {
1919                 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
1920                 IfFailGoto(E_FAIL, lFail);
1921             }
1922 #endif // FEATURE_COMINTEROP
1923
1924             if (!(nativeType == NATIVE_TYPE_FUNC || nativeType == NATIVE_TYPE_DEFAULT))
1925             {
1926                 m_resID = IDS_EE_BADMARSHAL_FNPTR;
1927                 IfFailGoto(E_FAIL, lFail);
1928             }
1929             m_type = ( (sizeof(void*)==4) ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8 );
1930             break;
1931
1932         case ELEMENT_TYPE_OBJECT:
1933         case ELEMENT_TYPE_STRING:
1934         case ELEMENT_TYPE_CLASS:
1935         case ELEMENT_TYPE_VAR:
1936         {                
1937             TypeHandle sigTH = sig.GetTypeHandleThrowing(pModule, pTypeContext);
1938
1939             // Disallow marshaling generic types except for WinRT interfaces.
1940             if (sigTH.HasInstantiation())
1941             {
1942 #ifdef FEATURE_COMINTEROP
1943                 if (!sigTH.SupportsGenericInterop(TypeHandle::Interop_NativeToManaged))
1944 #endif // FEATURE_COMINTEROP
1945                 {
1946                     m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
1947                     IfFailGoto(E_FAIL, lFail);
1948                 }
1949             }
1950             
1951             m_pMT = sigTH.GetMethodTable();
1952             if (m_pMT == NULL)
1953                 IfFailGoto(COR_E_TYPELOAD, lFail);
1954
1955 #ifdef FEATURE_COMINTEROP
1956             MethodTable* pDefaultMT = NULL;
1957
1958             // Look for marshaling of WinRT runtime classes
1959             if ((m_pMT->IsProjectedFromWinRT() || m_pMT->IsExportedToWinRT()) && !m_pMT->HasExplicitGuid())
1960             {
1961                 // The type loader guarantees that there are no WinRT interfaces without explicit GUID
1962                 _ASSERTE(!m_pMT->IsInterface());
1963
1964                 // Make sure that this is really a legal runtime class and not a custom attribute or delegate
1965                 if (!m_pMT->IsLegalNonArrayWinRTType() || m_pMT->IsDelegate())
1966                 {
1967                     m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
1968                     IfFailGoto(E_FAIL, lFail);
1969                 }
1970
1971                 // This class must have a default interface that describes how it is marshaled
1972                 pDefaultMT = m_pMT->GetDefaultWinRTInterface();
1973                 if (pDefaultMT == NULL)
1974                 {
1975                     m_resID = IDS_EE_BADMARSHAL_WINRT_MISSING_GUID;
1976                     IfFailGoto(E_FAIL, lFail);
1977                 }
1978             }
1979
1980             if (nativeType == NATIVE_TYPE_INTF)
1981             {
1982                 // whatever...
1983                 if (sig.IsStringType(pModule, pTypeContext)) 
1984                 {
1985                     m_resID = IDS_EE_BADMARSHALPARAM_STRING;
1986                     IfFailGoto(E_FAIL, lFail);
1987                 }
1988
1989                 if (m_ms == MARSHAL_SCENARIO_WINRT && COMDelegate::IsDelegate(m_pMT))
1990                 {
1991                     // In WinRT scenarios delegates must be WinRT delegates
1992                     if (!m_pMT->IsProjectedFromWinRT() && !WinRTTypeNameConverter::IsRedirectedType(m_pMT))
1993                     {
1994                         m_resID = IDS_EE_BADMARSHAL_WINRT_DELEGATE;
1995                         IfFailGoto(E_FAIL, lFail);
1996                     }
1997                 }
1998
1999                 m_type = MARSHAL_TYPE_INTERFACE;
2000             }
2001             else if (pDefaultMT != NULL && nativeType == NATIVE_TYPE_DEFAULT)
2002             {
2003                 // Pretend this is really marshaling as the default interface type
2004
2005                 // Validate it's a WinRT interface with GUID
2006                 if (!pDefaultMT->IsInterface() ||
2007                     (!pDefaultMT->IsProjectedFromWinRT() && !pDefaultMT->IsExportedToWinRT()) ||
2008                     !pDefaultMT->HasExplicitGuid())
2009                 {
2010                     // This might also be a redirected interface - which is also allowed
2011                     if (!pDefaultMT->IsWinRTRedirectedInterface(TypeHandle::Interop_NativeToManaged))
2012                     {
2013                         m_resID = IDS_EE_BADMARSHAL_DEFAULTIFACE_NOT_WINRT_IFACE;
2014                         IfFailGoto(E_FAIL, lFail);
2015                     }
2016                 }
2017
2018                 // Validate that it's one of the component interfaces of the class in the signature
2019                 if (!m_pMT->ImplementsEquivalentInterface(pDefaultMT))
2020                 {
2021                     m_resID = IDS_EE_BADMARSHAL_DEFAULTIFACE_NOT_SUBTYPE;
2022                     IfFailGoto(E_FAIL, lFail);
2023                 }
2024
2025                 // Make sure it's not an unexpected generic case (not clear we can actually get here in practice due
2026                 // to the above Implements check)
2027                 if (pDefaultMT->HasInstantiation() && !pDefaultMT->SupportsGenericInterop(TypeHandle::Interop_NativeToManaged))
2028                 {
2029                     m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
2030                     IfFailGoto(E_FAIL, lFail);
2031                 }
2032
2033                 // Store the marshal data just as if we were marshaling as this default interface type
2034                 m_type = MARSHAL_TYPE_INTERFACE;
2035                 m_pDefaultItfMT = pDefaultMT;
2036             }
2037             else
2038 #endif // FEATURE_COMINTEROP
2039             {
2040                 bool builder = false;
2041                 if (sig.IsStringTypeThrowing(pModule, pTypeContext) 
2042                     || ((builder = true), 0)
2043                     || sig.IsClassThrowing(pModule, g_StringBufferClassName, pTypeContext)
2044                     )
2045                 {
2046                     switch ( nativeType )
2047                     {
2048                         case NATIVE_TYPE_LPWSTR:
2049                             m_type = builder ? MARSHAL_TYPE_LPWSTR_BUFFER : MARSHAL_TYPE_LPWSTR;
2050                             break;
2051         
2052                         case NATIVE_TYPE_LPSTR:
2053                             m_type = builder ? MARSHAL_TYPE_LPSTR_BUFFER : MARSHAL_TYPE_LPSTR;
2054                             break;
2055
2056                         case NATIVE_TYPE_LPUTF8STR:
2057                             m_type = builder ? MARSHAL_TYPE_UTF8_BUFFER : MARSHAL_TYPE_LPUTF8STR;
2058                             break;
2059     
2060                         case NATIVE_TYPE_LPTSTR:
2061                         {
2062 #ifdef FEATURE_COMINTEROP
2063                             if (m_ms != MARSHAL_SCENARIO_NDIRECT)
2064                             {
2065                                 _ASSERTE(m_ms == MARSHAL_SCENARIO_COMINTEROP);
2066                                 // We disallow NATIVE_TYPE_LPTSTR for COM. 
2067                                 IfFailGoto(E_FAIL, lFail);
2068                             }
2069 #endif // FEATURE_COMINTEROP
2070                             // We no longer support Win9x so LPTSTR always maps to a Unicode string.
2071                             m_type = builder ? MARSHAL_TYPE_LPWSTR_BUFFER : MARSHAL_TYPE_LPWSTR;
2072                             break;
2073                         }
2074
2075                         case NATIVE_TYPE_BSTR:
2076                             if (builder)
2077                             {
2078                                 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2079                                 IfFailGoto(E_FAIL, lFail);
2080                             }
2081                             m_type = MARSHAL_TYPE_BSTR;
2082                             break;
2083
2084                         case NATIVE_TYPE_ANSIBSTR:
2085                             if (builder)
2086                             {
2087                                 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2088                                 IfFailGoto(E_FAIL, lFail);
2089                             }
2090                             m_type = MARSHAL_TYPE_ANSIBSTR;
2091                             break;
2092                             
2093                         case NATIVE_TYPE_TBSTR:
2094                         {
2095                             if (builder)
2096                             {
2097                                 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2098                                 IfFailGoto(E_FAIL, lFail);
2099                             }
2100                             
2101                             // We no longer support Win9x so TBSTR always maps to a normal (unicode) BSTR.
2102                             m_type = MARSHAL_TYPE_BSTR;
2103                             break;
2104                         }
2105
2106 #ifdef FEATURE_COMINTEROP
2107                         case NATIVE_TYPE_BYVALSTR:
2108                         {
2109                             if (builder)
2110                             {
2111                                 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2112                                 IfFailGoto(E_FAIL, lFail);
2113                             }
2114                             m_type = m_fAnsi ? MARSHAL_TYPE_VBBYVALSTR : MARSHAL_TYPE_VBBYVALSTRW;
2115                             break;
2116                         }
2117
2118                         case NATIVE_TYPE_HSTRING:
2119                         {
2120                             if (builder)
2121                             {
2122                                 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2123                                 IfFailGoto(E_FAIL, lFail);
2124                             }
2125
2126                             m_type = MARSHAL_TYPE_HSTRING;
2127                             break;
2128                         }
2129 #endif // FEATURE_COMINTEROP
2130     
2131                         case NATIVE_TYPE_DEFAULT:
2132                         {
2133 #ifdef FEATURE_COMINTEROP
2134                             if (m_ms == MARSHAL_SCENARIO_WINRT)
2135                             {
2136                                 if (builder)
2137                                 {
2138                                     m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2139                                     IfFailGoto(E_FAIL, lFail);
2140                                 }
2141
2142                                 m_type = MARSHAL_TYPE_HSTRING;
2143                             }
2144                             else if (m_ms != MARSHAL_SCENARIO_NDIRECT)
2145                             {
2146                                 _ASSERTE(m_ms == MARSHAL_SCENARIO_COMINTEROP);
2147                                 m_type = builder ? MARSHAL_TYPE_LPWSTR_BUFFER : MARSHAL_TYPE_BSTR;
2148                             }
2149                             else
2150 #endif // FEATURE_COMINTEROP
2151                             if (m_fAnsi)
2152                             {
2153                                 m_type = builder ? MARSHAL_TYPE_LPSTR_BUFFER : MARSHAL_TYPE_LPSTR;
2154                             }
2155                             else
2156                             {
2157                                 m_type = builder ? MARSHAL_TYPE_LPWSTR_BUFFER : MARSHAL_TYPE_LPWSTR;
2158                             }
2159                             break;
2160                         }
2161     
2162                         default:
2163                             m_resID = builder ? IDS_EE_BADMARSHALPARAM_STRINGBUILDER : IDS_EE_BADMARSHALPARAM_STRING;
2164                             IfFailGoto(E_FAIL, lFail);
2165                             break;
2166                     }
2167                 }
2168 #ifdef FEATURE_COMINTEROP
2169                 else if (sig.IsClassThrowing(pModule, g_CollectionsEnumeratorClassName, pTypeContext) && 
2170                          nativeType == NATIVE_TYPE_DEFAULT)
2171                 {
2172                     m_CMVt = VT_UNKNOWN;
2173                     m_type = MARSHAL_TYPE_REFERENCECUSTOMMARSHALER;
2174
2175                     if (fLoadCustomMarshal)
2176                     {
2177                         if (!fEmitsIL)
2178                         {
2179                             m_pCMHelper = SetupCustomMarshalerHelper(ENUMERATOR_TO_ENUM_VARIANT_CM_NAME, 
2180                                                                      ENUMERATOR_TO_ENUM_VARIANT_CM_NAME_LEN,
2181                                                                      ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE, 
2182                                                                      ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE_LEN, 
2183                                                                      pAssembly, sigTH);
2184                         }
2185                         else
2186                         {
2187                             m_pCMHelper = NULL;
2188                             MethodDesc* pMDforModule = pMD;
2189                             if (pMD->IsILStub())
2190                             {
2191                                 pMDforModule = pMD->AsDynamicMethodDesc()->GetILStubResolver()->GetStubTargetMethodDesc();
2192                             }
2193                             m_args.rcm.m_pMD = pMDforModule;
2194                             m_args.rcm.m_paramToken = token;
2195                             m_args.rcm.m_hndManagedType = sigTH.AsPtr();
2196                             CONSISTENCY_CHECK(pModule == pMDforModule->GetModule());
2197                         }
2198                     }
2199                 }
2200 #endif // FEATURE_COMINTEROP
2201                 else if (sigTH.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__SAFE_HANDLE))))
2202                 {
2203                     if (nativeType != NATIVE_TYPE_DEFAULT)
2204                     {
2205                         m_resID = IDS_EE_BADMARSHAL_SAFEHANDLE;
2206                         IfFailGoto(E_FAIL, lFail);
2207                     }
2208                     m_args.m_pMT = m_pMT;
2209                     m_type = MARSHAL_TYPE_SAFEHANDLE;
2210                 }
2211                 else if (sigTH.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__CRITICAL_HANDLE))))
2212                 {
2213                     if (nativeType != NATIVE_TYPE_DEFAULT)
2214                     {
2215                         m_resID = IDS_EE_BADMARSHAL_CRITICALHANDLE;
2216                         IfFailGoto(E_FAIL, lFail);
2217                     }
2218                     m_args.m_pMT = m_pMT;
2219                     m_type = MARSHAL_TYPE_CRITICALHANDLE;
2220                 }
2221                 else if (sig.IsClassThrowing(pModule, g_ReflectionMethodInterfaceName, pTypeContext))
2222                 {
2223                     if (nativeType != NATIVE_TYPE_DEFAULT)
2224                     {
2225                         IfFailGoto(E_FAIL, lFail);
2226                     }
2227
2228                     m_type = MARSHAL_TYPE_RUNTIMEMETHODINFO;
2229                 }
2230 #ifdef FEATURE_COMINTEROP
2231                 else if (m_pMT->IsInterface())
2232                 {
2233                     if (!(nativeType == NATIVE_TYPE_DEFAULT ||
2234                           nativeType == NATIVE_TYPE_INTF))
2235                     {
2236                         m_resID = IDS_EE_BADMARSHAL_INTERFACE;
2237                         IfFailGoto(E_FAIL, lFail);
2238                     }
2239                     m_type = MARSHAL_TYPE_INTERFACE;
2240
2241                     if (m_ms == MARSHAL_SCENARIO_WINRT)
2242                     {
2243                         // all interfaces marshaled in WinRT scenarios are IInspectable-based
2244                         m_fInspItf = TRUE;
2245                     }
2246                 }
2247                 // Check for Windows.Foundation.HResult <-> Exception
2248                 else if (m_ms == MARSHAL_SCENARIO_WINRT && MscorlibBinder::IsClass(m_pMT, CLASS__EXCEPTION))
2249                 {
2250                     m_args.m_pMT = m_pMT;
2251                     m_type = MARSHAL_TYPE_EXCEPTION;
2252                 }
2253 #endif // FEATURE_COMINTEROP
2254                 else if (COMDelegate::IsDelegate(m_pMT))
2255                 {
2256                     m_args.m_pMT = m_pMT;
2257 #ifdef FEATURE_COMINTEROP
2258                     if (m_ms == MARSHAL_SCENARIO_WINRT)
2259                     {
2260                         // Delegates must be imported from WinRT and marshaled as Interface
2261                         if (!m_pMT->IsProjectedFromWinRT() && !WinRTTypeNameConverter::IsRedirectedType(m_pMT))
2262                         {
2263                             m_resID = IDS_EE_BADMARSHAL_WINRT_DELEGATE;
2264                             IfFailGoto(E_FAIL, lFail);
2265                         }
2266                     }
2267 #endif // FEATURE_COMINTEROP
2268
2269                     switch (nativeType)
2270                     {
2271                         case NATIVE_TYPE_FUNC:
2272                             m_type = MARSHAL_TYPE_DELEGATE;
2273                             break;
2274
2275                         case NATIVE_TYPE_DEFAULT:
2276 #ifdef FEATURE_COMINTEROP
2277                             if (m_ms != MARSHAL_SCENARIO_NDIRECT)
2278                             {
2279                                 _ASSERTE(m_ms == MARSHAL_SCENARIO_COMINTEROP || m_ms == MARSHAL_SCENARIO_WINRT);
2280                                 m_type = MARSHAL_TYPE_INTERFACE;
2281                             }
2282                             else
2283 #endif // FEATURE_COMINTEROP
2284                                 m_type = MARSHAL_TYPE_DELEGATE;
2285
2286                             break;
2287
2288                         default:
2289                         m_resID = IDS_EE_BADMARSHAL_DELEGATE;
2290                         IfFailGoto(E_FAIL, lFail);
2291                             break;
2292                     }
2293                 }
2294                 else if (m_pMT->IsBlittable())
2295                 {
2296                     if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_LPSTRUCT))
2297                     {
2298                         m_resID = IDS_EE_BADMARSHAL_CLASS;
2299                         IfFailGoto(E_FAIL, lFail);
2300                     }
2301                     m_type = MARSHAL_TYPE_BLITTABLEPTR;
2302                     m_args.m_pMT = m_pMT;
2303                 }
2304                 else if (m_pMT->HasLayout())
2305                 {
2306                     if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_LPSTRUCT))
2307                     {
2308                         m_resID = IDS_EE_BADMARSHAL_CLASS;
2309                         IfFailGoto(E_FAIL, lFail);
2310                     }
2311                     m_type = MARSHAL_TYPE_LAYOUTCLASSPTR;
2312                     m_args.m_pMT = m_pMT;
2313                 }    
2314                 else if (sig.IsClassThrowing(pModule, g_ReflectionModuleName, pTypeContext))
2315                 {
2316                     if (nativeType != NATIVE_TYPE_DEFAULT)
2317                     {
2318                         IfFailGoto(E_FAIL, lFail);
2319                     }
2320
2321                     m_type = MARSHAL_TYPE_RUNTIMEMODULE;
2322                 }
2323                 else if (sig.IsClassThrowing(pModule, g_ReflectionAssemblyName, pTypeContext))
2324                 {
2325                     if (nativeType != NATIVE_TYPE_DEFAULT)
2326                     {
2327                         IfFailGoto(E_FAIL, lFail);
2328                     }
2329
2330                     m_type = MARSHAL_TYPE_RUNTIMEASSEMBLY;
2331                 }
2332 #ifdef FEATURE_COMINTEROP
2333                 else if (m_ms == MARSHAL_SCENARIO_WINRT && sig.IsClassThrowing(pModule, g_SystemUriClassName, pTypeContext))
2334                 {
2335                     m_type = MARSHAL_TYPE_URI;
2336                 }
2337                 else if (m_ms == MARSHAL_SCENARIO_WINRT && sig.IsClassThrowing(pModule, g_NotifyCollectionChangedEventArgsName, pTypeContext))
2338                 {
2339                     m_type = MARSHAL_TYPE_NCCEVENTARGS;
2340                 }
2341                 else if (m_ms == MARSHAL_SCENARIO_WINRT && sig.IsClassThrowing(pModule, g_PropertyChangedEventArgsName, pTypeContext))
2342                 {
2343                     m_type = MARSHAL_TYPE_PCEVENTARGS;
2344                 }
2345 #endif // FEATURE_COMINTEROP
2346                 else if (m_pMT->IsObjectClass())
2347                 {
2348                     switch(nativeType)
2349                     {
2350 #ifdef FEATURE_COMINTEROP
2351                         case NATIVE_TYPE_DEFAULT:
2352                             if (ms == MARSHAL_SCENARIO_WINRT)
2353                             {
2354                                 m_fInspItf = TRUE;
2355                                 m_type = MARSHAL_TYPE_INTERFACE;
2356                                 break;
2357                             }
2358                             // fall through
2359                         case NATIVE_TYPE_STRUCT:
2360                             m_type = MARSHAL_TYPE_OBJECT;
2361                             break;
2362
2363                         case NATIVE_TYPE_INTF:
2364                         case NATIVE_TYPE_IUNKNOWN:
2365                             m_type = MARSHAL_TYPE_INTERFACE;
2366                             break;
2367
2368                         case NATIVE_TYPE_IDISPATCH:
2369                             m_fDispItf = TRUE;
2370                             m_type = MARSHAL_TYPE_INTERFACE;
2371                             break;
2372
2373                         case NATIVE_TYPE_IINSPECTABLE:
2374                             m_fInspItf = TRUE;
2375                             m_type = MARSHAL_TYPE_INTERFACE;
2376                             break;
2377 #else
2378                         case NATIVE_TYPE_DEFAULT:
2379                         case NATIVE_TYPE_STRUCT:
2380                             m_resID = IDS_EE_OBJECT_TO_VARIANT_NOT_SUPPORTED;
2381                             IfFailGoto(E_FAIL, lFail);
2382
2383                         case NATIVE_TYPE_INTF:
2384                         case NATIVE_TYPE_IUNKNOWN:
2385                         case NATIVE_TYPE_IDISPATCH:
2386                             m_resID = IDS_EE_OBJECT_TO_ITF_NOT_SUPPORTED;
2387                             IfFailGoto(E_FAIL, lFail);
2388 #endif // FEATURE_COMINTEROP
2389
2390                         case NATIVE_TYPE_ASANY:
2391                             m_type = m_fAnsi ? MARSHAL_TYPE_ASANYA : MARSHAL_TYPE_ASANYW;
2392                             break;
2393
2394                         default:
2395                             m_resID = IDS_EE_BADMARSHAL_OBJECT;
2396                             IfFailGoto(E_FAIL, lFail);
2397                     }
2398                 }
2399                
2400 #ifdef FEATURE_COMINTEROP
2401                 else if (sig.IsClassThrowing(pModule, g_ArrayClassName, pTypeContext))
2402                 {            
2403                     if (IsWinRTScenario())
2404                     {
2405                         m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
2406                         IfFailGoto(E_FAIL, lFail);
2407                     }
2408
2409                     switch(nativeType)
2410                     {
2411                         case NATIVE_TYPE_DEFAULT:
2412                         case NATIVE_TYPE_INTF:
2413                             m_type = MARSHAL_TYPE_INTERFACE;
2414                             break;
2415
2416                         case NATIVE_TYPE_SAFEARRAY:
2417                         {
2418                             TypeHandle thElement = TypeHandle(g_pObjectClass);
2419                             
2420                             if (ParamInfo.m_SafeArrayElementVT != VT_EMPTY)
2421                             {
2422                                 if (ParamInfo.m_cSafeArrayUserDefTypeNameBytes > 0)
2423                                 {
2424                                     // Load the type. Use an SString for the string since we need to NULL terminate the string
2425                                     // that comes from the metadata.
2426                                     StackScratchBuffer utf8Name;
2427                                     SString safeArrayUserDefTypeName(SString::Utf8, ParamInfo.m_strSafeArrayUserDefTypeName, ParamInfo.m_cSafeArrayUserDefTypeNameBytes);
2428                                     thElement = TypeName::GetTypeUsingCASearchRules(safeArrayUserDefTypeName.GetUTF8(utf8Name), pAssembly);
2429                                 }
2430                             }
2431                             else
2432                             {
2433                                 // Compat: If no safe array VT was specified, default to VT_VARIANT.
2434                                 ParamInfo.m_SafeArrayElementVT = VT_VARIANT;
2435                             }
2436                             
2437                             IfFailGoto(HandleArrayElemType(&ParamInfo, 0, thElement, -1, FALSE, isParam, pAssembly), lFail);
2438                             break;
2439                         }
2440
2441                         default:
2442                             m_resID = IDS_EE_BADMARSHAL_SYSARRAY;
2443                             IfFailGoto(E_FAIL, lFail);
2444  
2445                     }
2446                 }
2447
2448                 else if (m_pMT->IsArray())
2449                 {                   
2450                     _ASSERTE(!"This invalid signature should never be hit!");
2451                     IfFailGoto(E_FAIL, lFail);
2452                 }
2453                 else if ((m_ms == MARSHAL_SCENARIO_WINRT) && sig.IsClassThrowing(pModule, g_TypeClassName, pTypeContext))
2454                 {
2455                     m_type = MARSHAL_TYPE_SYSTEMTYPE;
2456                 }
2457 #endif // FEATURE_COMINTEROP
2458                 else if (!m_pMT->IsValueType())
2459                 {
2460 #ifdef FEATURE_COMINTEROP
2461                     if (IsWinRTScenario() && !m_pMT->IsLegalNonArrayWinRTType())
2462                     {
2463                         m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
2464                         IfFailGoto(E_FAIL, lFail);
2465                     }
2466 #endif // FEATURE_COMINTEROP
2467
2468                     if (!(nativeType == NATIVE_TYPE_INTF || nativeType == NATIVE_TYPE_DEFAULT))
2469                     {
2470                         m_resID = IDS_EE_BADMARSHAL_NOLAYOUT;
2471                         IfFailGoto(E_FAIL, lFail);
2472                     }
2473 #ifdef FEATURE_COMINTEROP
2474                     // default marshalling is interface
2475                     m_type = MARSHAL_TYPE_INTERFACE;
2476 #else // FEATURE_COMINTEROP
2477                     m_resID = IDS_EE_OBJECT_TO_ITF_NOT_SUPPORTED;
2478                     IfFailGoto(E_FAIL, lFail);
2479 #endif // FEATURE_COMINTEROP
2480                 }
2481
2482                 else
2483                 {
2484                     _ASSERTE(m_pMT->IsValueType());
2485                     goto lValueClass;
2486                 }
2487             }
2488             break;
2489         }
2490
2491     
2492         case ELEMENT_TYPE_VALUETYPE:
2493         lValueClass:
2494         {
2495             if (sig.IsClassThrowing(pModule, g_DecimalClassName, pTypeContext))
2496             {
2497                 switch (nativeType)
2498                 {
2499                     case NATIVE_TYPE_DEFAULT:
2500                     case NATIVE_TYPE_STRUCT:
2501                         m_type = MARSHAL_TYPE_DECIMAL;
2502                         break;
2503
2504                     case NATIVE_TYPE_LPSTRUCT:
2505                         m_type = MARSHAL_TYPE_DECIMAL_PTR;
2506                         break;
2507
2508                     case NATIVE_TYPE_CURRENCY:
2509                         m_type = MARSHAL_TYPE_CURRENCY;
2510                         break;
2511
2512                     default:
2513                         m_resID = IDS_EE_BADMARSHALPARAM_DECIMAL;
2514                         IfFailGoto(E_FAIL, lFail);
2515                 }
2516             }
2517             else if (sig.IsClassThrowing(pModule, g_GuidClassName, pTypeContext))
2518             {
2519                 switch (nativeType)
2520                 {
2521                     case NATIVE_TYPE_DEFAULT:
2522                     case NATIVE_TYPE_STRUCT:
2523                         m_type = MARSHAL_TYPE_GUID;
2524                         break;
2525
2526                     case NATIVE_TYPE_LPSTRUCT:
2527                         m_type = MARSHAL_TYPE_GUID_PTR;
2528                         break;
2529
2530                     default:
2531                         m_resID = IDS_EE_BADMARSHAL_GUID;
2532                         IfFailGoto(E_FAIL, lFail);
2533                 }
2534             }
2535 #ifdef FEATURE_COMINTEROP
2536             else if (sig.IsClassThrowing(pModule, g_DateTimeOffsetClassName, pTypeContext))
2537             {
2538                 if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_STRUCT))
2539                 {
2540                     m_resID = IDS_EE_BADMARSHAL_DATETIMEOFFSET;
2541                     IfFailGoto(E_FAIL, lFail);
2542                 }
2543                 m_type = MARSHAL_TYPE_DATETIME;
2544                 m_pMT = MscorlibBinder::GetClass(CLASS__DATE_TIME_OFFSET);
2545             }           
2546 #endif  // FEATURE_COMINTEROP
2547             else if (sig.IsClassThrowing(pModule, g_DateClassName, pTypeContext))
2548             {
2549                 if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_STRUCT))
2550                 {
2551                     m_resID = IDS_EE_BADMARSHAL_DATETIME;
2552                     IfFailGoto(E_FAIL, lFail);
2553                 }
2554                 m_type = MARSHAL_TYPE_DATE;
2555             }
2556             else if (sig.IsClassThrowing(pModule, "System.Runtime.InteropServices.ArrayWithOffset", pTypeContext))
2557             {
2558                 if (!(nativeType == NATIVE_TYPE_DEFAULT))
2559                 {
2560                     IfFailGoto(E_FAIL, lFail);
2561                 }
2562                 m_type = MARSHAL_TYPE_ARRAYWITHOFFSET;
2563             }
2564             else if (sig.IsClassThrowing(pModule, "System.Runtime.InteropServices.HandleRef", pTypeContext))
2565             {
2566                 if (!(nativeType == NATIVE_TYPE_DEFAULT))
2567                 {
2568                     IfFailGoto(E_FAIL, lFail);
2569                 }
2570                 m_type = MARSHAL_TYPE_HANDLEREF;
2571             }
2572             else if (sig.IsClassThrowing(pModule, "System.ArgIterator", pTypeContext))
2573             {
2574                 if (!(nativeType == NATIVE_TYPE_DEFAULT))
2575                 {
2576                     IfFailGoto(E_FAIL, lFail);
2577                 }
2578                 m_type = MARSHAL_TYPE_ARGITERATOR;
2579             }
2580 #ifdef FEATURE_COMINTEROP
2581             else if (sig.IsClassThrowing(pModule, g_ColorClassName, pTypeContext))
2582             {
2583                 if (!(nativeType == NATIVE_TYPE_DEFAULT))
2584                 {
2585                     IfFailGoto(E_FAIL, lFail);
2586                 }
2587
2588                 // This is only supported for COM interop.
2589                 if (m_ms != MARSHAL_SCENARIO_COMINTEROP)
2590                 {
2591                     IfFailGoto(E_FAIL, lFail);
2592                 }
2593
2594                 m_type = MARSHAL_TYPE_OLECOLOR;
2595             }
2596 #endif // FEATURE_COMINTEROP
2597             else if (sig.IsClassThrowing(pModule, g_RuntimeTypeHandleClassName, pTypeContext))
2598             {
2599                 if (nativeType != NATIVE_TYPE_DEFAULT)
2600                 {
2601                     IfFailGoto(E_FAIL, lFail);
2602                 }
2603
2604                 m_type = MARSHAL_TYPE_RUNTIMETYPEHANDLE;
2605             }
2606             else if (sig.IsClassThrowing(pModule, g_RuntimeFieldHandleClassName, pTypeContext))
2607             {
2608                 if (nativeType != NATIVE_TYPE_DEFAULT)
2609                 {
2610                     IfFailGoto(E_FAIL, lFail);
2611                 }
2612
2613                 m_type = MARSHAL_TYPE_RUNTIMEFIELDHANDLE;
2614             }
2615             else if (sig.IsClassThrowing(pModule, g_RuntimeMethodHandleClassName, pTypeContext))
2616             {
2617                 if (nativeType != NATIVE_TYPE_DEFAULT)
2618                 {
2619                     IfFailGoto(E_FAIL, lFail);
2620                 }
2621
2622                 m_type = MARSHAL_TYPE_RUNTIMEMETHODHANDLE;
2623             }
2624             else
2625             {
2626                 m_pMT = sig.GetTypeHandleThrowing(pModule, pTypeContext).GetMethodTable();
2627                 if (m_pMT == NULL)
2628                     break;
2629
2630 #ifdef FEATURE_COMINTEROP
2631                 // Handle Nullable<T> and KeyValuePair<K, V> for WinRT
2632                 if (m_ms == MARSHAL_SCENARIO_WINRT)
2633                 {
2634                     if (m_pMT->HasSameTypeDefAs(g_pNullableClass))
2635                     {
2636                         m_type = MARSHAL_TYPE_NULLABLE;
2637                         m_args.m_pMT = m_pMT;
2638                         break;
2639                     }
2640
2641                     if (m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__KEYVALUEPAIRGENERIC)))
2642                     {
2643                         m_type = MARSHAL_TYPE_KEYVALUEPAIR;
2644                         m_args.m_pMT = m_pMT;
2645                         break;
2646                     }
2647
2648                     if (!m_pMT->IsLegalNonArrayWinRTType())
2649                     {
2650                         m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
2651                         IfFailGoto(E_FAIL, lFail);
2652                     }
2653                 }
2654 #endif // FEATURE_COMINTEROP
2655
2656                 if (m_pMT->HasInstantiation())
2657                 {
2658                     m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
2659                     IfFailGoto(E_FAIL, lFail);
2660                 }
2661
2662                 UINT managedSize = m_pMT->GetAlignedNumInstanceFieldBytes();
2663                 UINT  nativeSize = m_pMT->GetNativeSize();
2664                 
2665                 if ( nativeSize > 0xfff0 ||
2666                     managedSize > 0xfff0)
2667                 {
2668                     m_resID = IDS_EE_STRUCTTOOCOMPLEX;
2669                     IfFailGoto(E_FAIL, lFail);
2670                 }
2671
2672                 if (m_pMT->IsBlittable())
2673                 {
2674                     if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_STRUCT))
2675                     {
2676                         m_resID = IDS_EE_BADMARSHAL_VALUETYPE;
2677                         IfFailGoto(E_FAIL, lFail);
2678                     }
2679
2680                     if (m_byref && !isParam)
2681                     {
2682                         // Override the prohibition on byref returns so that IJW works
2683                         m_byref = FALSE;
2684                         m_type = ((sizeof(void*) == 4) ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8);
2685                     }
2686                     else
2687                     {
2688 #ifdef _TARGET_X86_
2689                         // JIT64 is not aware of normalized value types and this optimization
2690                         // (returning small value types by value in registers) is already done in JIT64.
2691                         if (        !m_byref   // Permit register-sized structs as return values
2692                                  && !isParam
2693                                  && CorIsPrimitiveType(m_pMT->GetInternalCorElementType())
2694                                  && !IsUnmanagedValueTypeReturnedByRef(nativeSize)
2695                                  && managedSize <= sizeof(void*)
2696                                  && nativeSize <= sizeof(void*))
2697                         {
2698                             m_type = MARSHAL_TYPE_GENERIC_4;
2699                             m_args.m_pMT = m_pMT;
2700                         }
2701                         else
2702 #endif // _TARGET_X86_
2703                         {
2704                             m_args.m_pMT = m_pMT;
2705                             m_type = MARSHAL_TYPE_BLITTABLEVALUECLASS;
2706                         }
2707                     }
2708                 }
2709                 else if (m_pMT->HasLayout())
2710                 {
2711                     if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_STRUCT))
2712                     {
2713                         m_resID = IDS_EE_BADMARSHAL_VALUETYPE;
2714                         IfFailGoto(E_FAIL, lFail);
2715                     }
2716
2717                     m_args.m_pMT = m_pMT;
2718                     m_type = MARSHAL_TYPE_VALUECLASS;
2719                 }
2720             }
2721             break;
2722         }
2723     
2724         case ELEMENT_TYPE_SZARRAY:
2725         case ELEMENT_TYPE_ARRAY:
2726         {
2727             // Get class info from array.
2728             TypeHandle arrayTypeHnd = sig.GetTypeHandleThrowing(pModule, pTypeContext);
2729             _ASSERTE(!arrayTypeHnd.IsNull());
2730
2731             ArrayTypeDesc* asArray = arrayTypeHnd.AsArray();
2732             if (asArray == NULL)
2733                 IfFailGoto(E_FAIL, lFail);
2734
2735             TypeHandle thElement = asArray->GetTypeParam();
2736
2737 #ifdef FEATURE_COMINTEROP
2738             if (m_ms != MARSHAL_SCENARIO_WINRT)
2739 #endif // FEATURE_COMINTEROP
2740             {
2741                 if (thElement.HasInstantiation())
2742                 {
2743                     m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
2744                     IfFailGoto(E_FAIL, lFail);
2745                 }
2746             }
2747
2748             unsigned ofs = 0;
2749             if (arrayTypeHnd.GetMethodTable())
2750             {
2751                 ofs = ArrayBase::GetDataPtrOffset(arrayTypeHnd.GetMethodTable());
2752                 if (ofs > 0xffff)
2753                 {
2754                     ofs = 0;   // can't represent it, so pass on magic value (which causes fallback to regular ML code)
2755                 }
2756             }
2757
2758             // Handle retrieving the information for the array type.
2759             IfFailGoto(HandleArrayElemType(&ParamInfo, (UINT16)ofs, thElement, asArray->GetRank(), mtype == ELEMENT_TYPE_SZARRAY, isParam, pAssembly), lFail);
2760             break;
2761         }
2762         
2763         default:
2764             m_resID = IDS_EE_BADMARSHAL_BADMANAGED;
2765     }
2766
2767 lExit:
2768 #ifdef FEATURE_COMINTEROP
2769 //Field scenario is not blocked here because we don't want to block loading structs that 
2770 //have the types which we are blocking, but never pass it to Interop.
2771
2772     if (AppX::IsAppXProcess() && ms != MarshalInfo::MARSHAL_SCENARIO_FIELD)
2773     {
2774         bool set_error = false;
2775         switch (m_type)
2776         {
2777             case MARSHAL_TYPE_ANSIBSTR: 
2778                 m_resID = IDS_EE_BADMARSHAL_TYPE_ANSIBSTR;
2779                 set_error = true;
2780                 break;
2781             case MARSHAL_TYPE_VBBYVALSTR:
2782             case MARSHAL_TYPE_VBBYVALSTRW:
2783                 m_resID = IDS_EE_BADMARSHAL_TYPE_VBBYVALSTR;
2784                 set_error = true;
2785                 break;
2786             case MARSHAL_TYPE_REFERENCECUSTOMMARSHALER:
2787                 m_resID = IDS_EE_BADMARSHAL_TYPE_REFERENCECUSTOMMARSHALER;
2788                 set_error = true;
2789                 break;
2790             case MARSHAL_TYPE_ASANYA: 
2791             case MARSHAL_TYPE_ASANYW: 
2792                 m_resID = IDS_EE_BADMARSHAL_TYPE_ASANYA;
2793                 set_error = true;
2794                 break;
2795             case MARSHAL_TYPE_INTERFACE:
2796                 if (m_fDispItf)
2797                 {
2798                     m_resID = IDS_EE_BADMARSHAL_TYPE_IDISPATCH;
2799                     set_error = true;
2800                 }
2801                 break;
2802         }
2803
2804         if (set_error)
2805             COMPlusThrow(kPlatformNotSupportedException, m_resID);
2806
2807     }
2808     
2809     if (IsWinRTScenario() && !IsSupportedForWinRT(m_type))
2810     {
2811         // the marshaler we came up with is not supported in WinRT scenarios
2812         m_type = MARSHAL_TYPE_UNKNOWN;
2813         m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
2814         goto lReallyExit;
2815     }
2816 #endif // FEATURE_COMINTEROP
2817
2818     if (m_byref && !isParam)
2819     {
2820         // byref returns don't work: the thing pointed to lives on
2821         // a stack that disappears!
2822         m_type = MARSHAL_TYPE_UNKNOWN;
2823         goto lReallyExit;
2824     }
2825    
2826     //---------------------------------------------------------------------
2827     // Now, figure out the IN/OUT status.
2828     // Also set the m_fOleVarArgCandidate here to save perf of invoking Metadata API
2829     //---------------------------------------------------------------------
2830     m_fOleVarArgCandidate = FALSE;
2831     if (m_type != MARSHAL_TYPE_UNKNOWN && IsInOnly(m_type) && !m_byref)
2832     {
2833         // If we got here, the parameter is something like an "int" where
2834         // [in] is the only semantically valid choice. Since there is no
2835         // possible way to interpret an [out] for such a type, we will ignore
2836         // the metadata and force the bits to "in". We could have defined
2837         // it as an error instead but this is less likely to cause problems
2838         // with metadata autogenerated from typelibs and poorly
2839         // defined C headers.
2840         // 
2841         m_in = TRUE;
2842         m_out = FALSE;
2843     }
2844     else
2845     {
2846
2847         // Capture and save away "In/Out" bits. If none is present, set both to FALSE (they will be properly defaulted downstream)
2848         if (token == mdParamDefNil)
2849         {
2850             m_in = FALSE;
2851             m_out = FALSE;
2852         }
2853         else if (TypeFromToken(token) != mdtParamDef)
2854         {
2855             _ASSERTE(TypeFromToken(token) == mdtFieldDef);
2856
2857             // Field setters are always In, the flags are ignored for return values of getters
2858             m_in = TRUE;
2859             m_out = FALSE;
2860         }
2861         else
2862         {
2863             IMDInternalImport *pInternalImport = pModule->GetMDImport();
2864             USHORT             usSequence;
2865             DWORD              dwAttr;
2866             LPCSTR             szParamName_Ignore;
2867             
2868             if (FAILED(pInternalImport->GetParamDefProps(token, &usSequence, &dwAttr, &szParamName_Ignore)))
2869             {
2870                 m_in = FALSE;
2871                 m_out = FALSE;
2872             }
2873             else
2874             {
2875                 m_in = IsPdIn(dwAttr) != 0;
2876                 m_out = IsPdOut(dwAttr) != 0;
2877 #ifdef FEATURE_COMINTEROP
2878                 // set m_fOleVarArgCandidate. The rule is same as the one defined in vm\tlbexp.cpp
2879                 if(paramidx == numArgs &&                   // arg is the last arg of the method
2880                    !(dwAttr & PARAMFLAG_FOPT) &&            // arg is not a optional arg
2881                    !IsNilToken(token) &&                    // token is not a nil token
2882                    (m_type == MARSHAL_TYPE_SAFEARRAY) &&    // arg is marshaled as SafeArray
2883                    (m_arrayElementType == VT_VARIANT))      // the element of the safearray is VARIANT
2884                 {
2885                     // check if it has default value
2886                     MDDefaultValue defaultValue;
2887                     if (SUCCEEDED(pInternalImport->GetDefaultValue(token, &defaultValue)) && defaultValue.m_bType == ELEMENT_TYPE_VOID)
2888                     {
2889                         // check if it has params attribute
2890                         if (pInternalImport->GetCustomAttributeByName(token, INTEROP_PARAMARRAY_TYPE, 0,0) == S_OK)
2891                             m_fOleVarArgCandidate = TRUE;
2892                     }
2893                 }
2894 #endif
2895             }
2896         }
2897         
2898         // If neither IN nor OUT are true, this signals the URT to use the default
2899         // rules.
2900         if (!m_in && !m_out)
2901         {
2902             if (m_byref || 
2903                  (mtype == ELEMENT_TYPE_CLASS 
2904                   && !(sig.IsStringType(pModule, pTypeContext))
2905                   && sig.IsClass(pModule, g_StringBufferClassName, pTypeContext)))
2906             {
2907                 m_in = TRUE;
2908                 m_out = TRUE;
2909             }
2910             else
2911             {
2912                 m_in = TRUE;
2913                 m_out = FALSE;
2914             }
2915         
2916         }
2917     }
2918     
2919 lReallyExit:
2920     
2921 #ifdef _DEBUG
2922     DumpMarshalInfo(pModule, sig, pTypeContext, token, ms, nlType, nlFlags); 
2923 #endif
2924     return;
2925     
2926     
2927   lFail:
2928     // We got here because of an illegal ELEMENT_TYPE/NATIVE_TYPE combo.
2929     m_type = MARSHAL_TYPE_UNKNOWN;
2930     //_ASSERTE(!"Invalid ELEMENT_TYPE/NATIVE_TYPE combination");
2931     goto lExit;
2932 }
2933 #ifdef _PREFAST_
2934 #pragma warning(pop)
2935 #endif
2936
2937 VOID MarshalInfo::EmitOrThrowInteropParamException(NDirectStubLinker* psl, BOOL fMngToNative, UINT resID, UINT paramIdx)
2938 {
2939     CONTRACTL
2940     {
2941         THROWS;
2942         GC_TRIGGERS;
2943         MODE_ANY;
2944     }
2945     CONTRACTL_END;
2946
2947 #ifdef FEATURE_COMINTEROP
2948     // If this is not forward COM interop, throw the exception right away. We rely on this
2949     // for example in code:ComPreStubWorker when we fire the InvalidMemberDeclaration MDA.
2950     if ((m_ms == MARSHAL_SCENARIO_COMINTEROP || m_ms == MARSHAL_SCENARIO_WINRT) && fMngToNative)
2951     {
2952         psl->SetInteropParamExceptionInfo(resID, paramIdx);
2953         return;
2954     }
2955 #endif // FEATURE_COMINTEROP
2956
2957     ThrowInteropParamException(resID, paramIdx);
2958 }
2959
2960
2961 HRESULT MarshalInfo::HandleArrayElemType(NativeTypeParamInfo *pParamInfo, UINT16 optbaseoffset,  TypeHandle thElement, int iRank, BOOL fNoLowerBounds, BOOL isParam, Assembly *pAssembly)
2962 {
2963     CONTRACTL
2964     {
2965         STANDARD_VM_CHECK;
2966         PRECONDITION(CheckPointer(pParamInfo));
2967     }
2968     CONTRACTL_END;
2969
2970     ArrayMarshalInfo arrayMarshalInfo(amiRuntime);
2971     
2972
2973     //
2974     // Store rank and bound information.
2975     //
2976
2977     m_iArrayRank = iRank;
2978     m_nolowerbounds = fNoLowerBounds;
2979
2980
2981     //
2982     // Determine which type of marshaler to use.
2983     //
2984
2985 #ifdef FEATURE_COMINTEROP
2986     if (m_ms == MARSHAL_SCENARIO_WINRT)
2987     {
2988         m_type = MARSHAL_TYPE_HIDDENLENGTHARRAY;
2989     }
2990     else if (pParamInfo->m_NativeType == NATIVE_TYPE_SAFEARRAY)
2991     {
2992         m_type = MARSHAL_TYPE_SAFEARRAY;
2993     }
2994     else
2995 #endif // FEATURE_COMINTEROP
2996     if (pParamInfo->m_NativeType == NATIVE_TYPE_ARRAY)
2997     {
2998         m_type = MARSHAL_TYPE_NATIVEARRAY;
2999     }
3000     else if (pParamInfo->m_NativeType == NATIVE_TYPE_DEFAULT)
3001     {
3002 #ifdef FEATURE_COMINTEROP
3003         if (m_ms != MARSHAL_SCENARIO_NDIRECT)
3004         {
3005             m_type = MARSHAL_TYPE_SAFEARRAY;
3006         }
3007         else
3008 #endif // FEATURE_COMINTEROP
3009         {
3010             m_type = MARSHAL_TYPE_NATIVEARRAY;
3011         }
3012     }
3013     else
3014     {
3015         m_resID = IDS_EE_BADMARSHAL_ARRAY;
3016         return E_FAIL;
3017     }
3018
3019 #ifdef FEATURE_COMINTEROP
3020     if (m_type == MARSHAL_TYPE_SAFEARRAY)
3021     {
3022         arrayMarshalInfo.InitForSafeArray(m_ms, thElement, pParamInfo->m_SafeArrayElementVT, m_fAnsi);
3023     }
3024     else if (m_type == MARSHAL_TYPE_HIDDENLENGTHARRAY)
3025     {
3026         arrayMarshalInfo.InitForHiddenLengthArray(thElement);
3027     }
3028     else
3029 #endif // FEATURE_COMINTEROP
3030     {
3031         _ASSERTE(m_type == MARSHAL_TYPE_NATIVEARRAY);
3032         arrayMarshalInfo.InitForNativeArray(m_ms, thElement, pParamInfo->m_ArrayElementType, m_fAnsi);
3033     }
3034
3035     // Make sure the marshalling information is valid.
3036     if (!arrayMarshalInfo.IsValid())
3037     {
3038         m_resID = arrayMarshalInfo.GetErrorResourceId();
3039         return E_FAIL;
3040     }
3041
3042     // Set the array type handle and VARTYPE to use for marshalling.
3043     m_hndArrayElemType = arrayMarshalInfo.GetElementTypeHandle();
3044     m_arrayElementType = arrayMarshalInfo.GetElementVT();
3045
3046     if (m_type == MARSHAL_TYPE_NATIVEARRAY)
3047     {
3048         // Retrieve the extra information associated with the native array marshaling.
3049         m_args.na.m_vt  = m_arrayElementType;
3050         m_args.na.m_pMT = !m_hndArrayElemType.IsTypeDesc() ? m_hndArrayElemType.AsMethodTable() : NULL;   
3051         m_args.na.m_optionalbaseoffset = optbaseoffset;
3052         m_countParamIdx = pParamInfo->m_CountParamIdx;
3053         m_multiplier    = pParamInfo->m_Multiplier;
3054         m_additive      = pParamInfo->m_Additive;
3055     }
3056 #ifdef FEATURE_COMINTEROP
3057     else if (m_type == MARSHAL_TYPE_HIDDENLENGTHARRAY)
3058     {
3059         m_args.na.m_optionalbaseoffset = optbaseoffset;
3060
3061         m_args.na.m_vt  = m_arrayElementType;
3062         m_args.na.m_pMT = m_hndArrayElemType.AsMethodTable();
3063         m_args.na.m_cbElementSize = arrayMarshalInfo.GetElementSize();
3064         m_args.na.m_redirectedTypeIndex = arrayMarshalInfo.GetRedirectedTypeIndex();
3065     }
3066 #endif // FEATURE_COMINTEROP
3067
3068     return S_OK;
3069 }
3070
3071 ILMarshaler* CreateILMarshaler(MarshalInfo::MarshalType mtype, NDirectStubLinker* psl)
3072 {
3073     CONTRACTL
3074     {
3075         THROWS;
3076         GC_NOTRIGGER;
3077         SO_TOLERANT;
3078         MODE_ANY;
3079     }
3080     CONTRACTL_END;
3081     ILMarshaler* pMarshaler = NULL;
3082     switch (mtype)
3083     {
3084
3085 #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) \
3086         case MarshalInfo::mt: \
3087             pMarshaler = new IL##mclass(); \
3088             break; 
3089 #include "mtypes.h"
3090 #undef DEFINE_MARSHALER_TYPE
3091
3092         default:
3093             UNREACHABLE_MSG("unexpected MarshalType passed to CreateILMarshaler");
3094     }
3095
3096     pMarshaler->SetNDirectStubLinker(psl);
3097     return pMarshaler;
3098 }
3099
3100
3101
3102 DWORD CalculateArgumentMarshalFlags(BOOL byref, BOOL in, BOOL out, BOOL fMngToNative)
3103 {
3104     LIMITED_METHOD_CONTRACT;
3105     DWORD dwMarshalFlags = 0;
3106
3107     if (byref)
3108     {
3109         dwMarshalFlags |= MARSHAL_FLAG_BYREF;
3110     }
3111
3112     if (in)
3113     {
3114         dwMarshalFlags |= MARSHAL_FLAG_IN;
3115     }
3116
3117     if (out)
3118     {
3119         dwMarshalFlags |= MARSHAL_FLAG_OUT;
3120     }
3121
3122     if (fMngToNative)
3123     {
3124         dwMarshalFlags |= MARSHAL_FLAG_CLR_TO_NATIVE;
3125     }
3126
3127     return dwMarshalFlags;
3128 }
3129
3130 DWORD CalculateReturnMarshalFlags(BOOL hrSwap, BOOL fMngToNative)
3131 {
3132     LIMITED_METHOD_CONTRACT;
3133     DWORD dwMarshalFlags = MARSHAL_FLAG_RETVAL;
3134
3135     if (hrSwap)
3136     {
3137         dwMarshalFlags |= MARSHAL_FLAG_HRESULT_SWAP;
3138     }
3139
3140     if (fMngToNative)
3141     {
3142         dwMarshalFlags |= MARSHAL_FLAG_CLR_TO_NATIVE;
3143     }
3144
3145     return dwMarshalFlags;
3146 }
3147
3148 void MarshalInfo::GenerateArgumentIL(NDirectStubLinker* psl,
3149                                      int argOffset, // the argument's index is m_paramidx + argOffset
3150                                      UINT nativeStackOffset, // offset of the argument on the native stack
3151                                      BOOL fMngToNative)
3152 {
3153     CONTRACTL
3154     {
3155         STANDARD_VM_CHECK;
3156         PRECONDITION(CheckPointer(psl));
3157     }
3158     CONTRACTL_END;
3159
3160     if (m_type == MARSHAL_TYPE_UNKNOWN)
3161     {
3162         EmitOrThrowInteropParamException(psl, fMngToNative, m_resID, m_paramidx + 1); // m_paramidx is 0-based, but the user wants to see a 1-based index
3163         return;
3164     }
3165
3166     // set up m_corArgSize and m_nativeArgSize
3167     SetupArgumentSizes();
3168
3169     MarshalerOverrideStatus amostat;
3170     UINT resID = IDS_EE_BADMARSHAL_RESTRICTION;
3171     amostat = (GetArgumentOverrideProc(m_type)) (psl,
3172                                              m_byref,
3173                                              m_in,
3174                                              m_out,
3175                                              fMngToNative,
3176                                              &m_args,
3177                                              &resID,
3178                                              m_paramidx + argOffset,
3179                                              nativeStackOffset);
3180
3181
3182     if (amostat == OVERRIDDEN)
3183     {
3184         return;
3185     }
3186     
3187     if (amostat == DISALLOWED)
3188     {
3189         EmitOrThrowInteropParamException(psl, fMngToNative, resID, m_paramidx + 1); // m_paramidx is 0-based, but the user wants to see a 1-based index
3190         return;
3191     }
3192
3193     CONSISTENCY_CHECK(amostat == HANDLEASNORMAL);
3194
3195     NewHolder<ILMarshaler> pMarshaler = CreateILMarshaler(m_type, psl);
3196     DWORD dwMarshalFlags = CalculateArgumentMarshalFlags(m_byref, m_in, m_out, fMngToNative);
3197
3198     if (!pMarshaler->SupportsArgumentMarshal(dwMarshalFlags, &resID))
3199     {
3200         EmitOrThrowInteropParamException(psl, fMngToNative, resID, m_paramidx + 1); // m_paramidx is 0-based, but the user wants to see a 1-based index
3201         return;
3202     }
3203
3204     ILCodeStream* pcsMarshal    = psl->GetMarshalCodeStream();
3205     ILCodeStream* pcsUnmarshal  = psl->GetUnmarshalCodeStream();
3206     ILCodeStream* pcsDispatch   = psl->GetDispatchCodeStream();
3207
3208     pcsMarshal->EmitNOP("// argument { ");
3209     pcsUnmarshal->EmitNOP("// argument { ");
3210
3211     pMarshaler->EmitMarshalArgument(pcsMarshal, pcsUnmarshal, m_paramidx + argOffset, dwMarshalFlags, &m_args);
3212
3213     //
3214     // Increment a counter so that when the finally clause 
3215     // is run, we only run the cleanup that is needed.
3216     //
3217     if (pMarshaler->NeedsMarshalCleanupIndex())
3218     {
3219         // we don't bother writing to the counter if marshaling does not need cleanup
3220         psl->EmitSetArgMarshalIndex(pcsMarshal, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_paramidx + argOffset);
3221     }
3222     if (pMarshaler->NeedsUnmarshalCleanupIndex())
3223     {
3224         // we don't bother writing to the counter if unmarshaling does not need exception cleanup
3225         psl->EmitSetArgMarshalIndex(pcsUnmarshal, NDirectStubLinker::CLEANUP_INDEX_ARG0_UNMARSHAL + m_paramidx + argOffset);
3226     }
3227
3228     pcsMarshal->EmitNOP("// } argument");
3229     pcsUnmarshal->EmitNOP("// } argument");
3230
3231     pMarshaler->EmitSetupArgument(pcsDispatch);
3232     if (m_paramidx == 0)
3233     {
3234         CorCallingConvention callConv = psl->GetStubTargetCallingConv();
3235         if ((callConv & IMAGE_CEE_CS_CALLCONV_MASK) == IMAGE_CEE_UNMANAGED_CALLCONV_THISCALL)
3236         {
3237             // Make sure the 'this' argument to thiscall is of native int type; JIT asserts this.
3238             pcsDispatch->EmitCONV_I();
3239         }
3240     }
3241 }
3242
3243 void MarshalInfo::GenerateReturnIL(NDirectStubLinker* psl,
3244                                    int argOffset,
3245                                    BOOL fMngToNative,
3246                                    BOOL fieldGetter,
3247                                    BOOL retval)
3248 {
3249     CONTRACTL
3250     {
3251         STANDARD_VM_CHECK;
3252         PRECONDITION(CheckPointer(psl));
3253     }
3254     CONTRACTL_END;
3255     
3256     MarshalerOverrideStatus amostat;
3257     UINT resID = IDS_EE_BADMARSHAL_RESTRICTION;
3258
3259     if (m_type == MARSHAL_TYPE_UNKNOWN)
3260     {
3261         amostat = HANDLEASNORMAL;
3262     }
3263     else
3264     {
3265         amostat = (GetReturnOverrideProc(m_type)) (psl,
3266                                                    fMngToNative,
3267                                                    retval,
3268                                                    &m_args,
3269                                                    &resID);
3270     }
3271
3272     if (amostat == DISALLOWED)
3273     {
3274         EmitOrThrowInteropParamException(psl, fMngToNative, resID, 0);
3275         return;
3276     }
3277         
3278     if (amostat == HANDLEASNORMAL)
3279     {
3280         // Historically we have always allowed reading fields that are marshaled as C arrays.
3281         if (m_type == MARSHAL_TYPE_UNKNOWN || (!fieldGetter && m_type == MARSHAL_TYPE_NATIVEARRAY))
3282         {
3283             EmitOrThrowInteropParamException(psl, fMngToNative, m_resID, 0);
3284             return;
3285         }
3286     
3287         NewHolder<ILMarshaler> pMarshaler = CreateILMarshaler(m_type, psl);
3288         DWORD dwMarshalFlags = CalculateReturnMarshalFlags(retval, fMngToNative);
3289
3290         if (!pMarshaler->SupportsReturnMarshal(dwMarshalFlags, &resID))
3291         {
3292             EmitOrThrowInteropParamException(psl, fMngToNative, resID, 0);
3293             return;
3294         }
3295
3296         ILCodeStream* pcsMarshal    = psl->GetMarshalCodeStream();
3297         ILCodeStream* pcsUnmarshal  = psl->GetReturnUnmarshalCodeStream();
3298         ILCodeStream* pcsDispatch   = psl->GetDispatchCodeStream();
3299             
3300         pcsMarshal->EmitNOP("// return { ");
3301         pcsUnmarshal->EmitNOP("// return { ");
3302             
3303         UINT16 wNativeSize = GetNativeSize(m_type, m_ms);
3304
3305         // The following statement behaviour has existed for a long time. By aligning the size of the return
3306         // value up to stack slot size, we prevent EmitMarshalReturnValue from distinguishing between, say, 3-byte
3307         // structure and 4-byte structure. The former is supposed to be returned by-ref using a secret argument
3308         // (at least in MSVC compiled code) while the latter is returned in EAX. We are keeping the behavior for
3309         // now for backward compatibility.
3310         X86_ONLY(wNativeSize = StackElemSize(wNativeSize));
3311
3312         pMarshaler->EmitMarshalReturnValue(pcsMarshal, pcsUnmarshal, pcsDispatch, m_paramidx + argOffset, wNativeSize, dwMarshalFlags, &m_args);
3313
3314         pcsMarshal->EmitNOP("// } return");
3315         pcsUnmarshal->EmitNOP("// } return");
3316
3317         return;
3318     }
3319 }
3320
3321 void MarshalInfo::SetupArgumentSizes()
3322 {
3323     CONTRACTL
3324     {
3325         NOTHROW;
3326         GC_NOTRIGGER;
3327         MODE_ANY;
3328     }
3329     CONTRACTL_END;
3330
3331     if (m_byref)
3332     {
3333         m_managedArgSize = StackElemSize(sizeof(void*));
3334         m_nativeArgSize = StackElemSize(sizeof(void*));
3335     }
3336     else
3337     {
3338         m_managedArgSize = StackElemSize(GetManagedSize(m_type, m_ms));
3339         m_nativeArgSize = StackElemSize(GetNativeSize(m_type, m_ms));
3340     }
3341
3342 #ifdef ENREGISTERED_PARAMTYPE_MAXSIZE
3343     if (m_managedArgSize > ENREGISTERED_PARAMTYPE_MAXSIZE)
3344         m_managedArgSize = StackElemSize(sizeof(void*));
3345
3346     if (m_nativeArgSize > ENREGISTERED_PARAMTYPE_MAXSIZE)
3347         m_nativeArgSize = StackElemSize(sizeof(void*));
3348 #endif // ENREGISTERED_PARAMTYPE_MAXSIZE
3349 }
3350
3351 UINT16 MarshalInfo::GetManagedSize(MarshalType mtype, MarshalScenario ms)
3352 {
3353     CONTRACTL
3354     {
3355         NOTHROW;
3356         GC_NOTRIGGER;
3357         MODE_ANY;
3358     }
3359     CONTRACTL_END;
3360     
3361     static const BYTE managedSizes[]=
3362     {
3363         #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) IL##mclass::c_CLRSize,
3364         #include "mtypes.h"
3365     };
3366
3367     _ASSERTE((SIZE_T)mtype < COUNTOF(managedSizes));
3368     BYTE managedSize = managedSizes[mtype];
3369
3370     if (managedSize == VARIABLESIZE)
3371     {
3372         switch (mtype)
3373         {
3374
3375             case MARSHAL_TYPE_BLITTABLEVALUECLASS:
3376             case MARSHAL_TYPE_VALUECLASS:
3377 #ifdef FEATURE_COMINTEROP
3378             case MARSHAL_TYPE_DATETIME:
3379             case MARSHAL_TYPE_NULLABLE:
3380             case MARSHAL_TYPE_KEYVALUEPAIR:
3381 #endif // FEATURE_COMINTEROP
3382                 return (UINT16) m_pMT->GetAlignedNumInstanceFieldBytes();
3383                 break;
3384
3385             default:
3386                 _ASSERTE(0);
3387         }
3388     }
3389
3390     return managedSize;
3391 }
3392
3393 UINT16 MarshalInfo::GetNativeSize(MarshalType mtype, MarshalScenario ms)
3394 {
3395     CONTRACTL
3396     {
3397         NOTHROW;
3398         GC_NOTRIGGER;
3399         MODE_ANY;
3400     }
3401     CONTRACTL_END;
3402     
3403     static const BYTE nativeSizes[]=
3404     {
3405         #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) IL##mclass::c_nativeSize,
3406         #include "mtypes.h"
3407     };
3408
3409     _ASSERTE((SIZE_T)mtype < COUNTOF(nativeSizes));
3410     BYTE nativeSize = nativeSizes[mtype];
3411
3412     if (nativeSize == VARIABLESIZE)
3413     {
3414         switch (mtype)
3415         {
3416             case MARSHAL_TYPE_BLITTABLEVALUECLASS:
3417             case MARSHAL_TYPE_VALUECLASS:
3418                 return (UINT16) m_pMT->GetNativeSize();
3419
3420             default:
3421                 _ASSERTE(0);
3422         }
3423     }
3424
3425     return nativeSize;
3426 }
3427
3428 bool MarshalInfo::IsInOnly(MarshalType mtype)
3429 {
3430     CONTRACTL
3431     {
3432         NOTHROW;
3433         GC_NOTRIGGER;
3434         MODE_ANY;
3435     }
3436     CONTRACTL_END;
3437     
3438     static const bool ILMarshalerIsInOnly[] =
3439     {
3440         #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) \
3441             (IL##mclass::c_fInOnly ? true : false),
3442
3443         #include "mtypes.h"
3444     };
3445
3446     return ILMarshalerIsInOnly[mtype];
3447 }
3448
3449 bool MarshalInfo::IsSupportedForWinRT(MarshalType mtype)
3450 {
3451     CONTRACTL
3452     {
3453         NOTHROW;
3454         GC_NOTRIGGER;
3455         MODE_ANY;
3456     }
3457     CONTRACTL_END;
3458     
3459     static const bool MarshalerSupportsWinRT[] =
3460     {
3461         #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) \
3462             fWinRTSupported,
3463
3464         #include "mtypes.h"
3465     };
3466
3467     return MarshalerSupportsWinRT[mtype];
3468 }
3469
3470 OVERRIDEPROC MarshalInfo::GetArgumentOverrideProc(MarshalType mtype)
3471 {
3472     CONTRACTL
3473     {
3474         NOTHROW;
3475         GC_NOTRIGGER;
3476         MODE_ANY;
3477     }
3478     CONTRACTL_END;
3479     
3480     static const OVERRIDEPROC ILArgumentOverrideProcs[] =
3481     {
3482         #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) IL##mclass::ArgumentOverride,
3483         #include "mtypes.h"
3484     };
3485
3486     _ASSERTE((SIZE_T)mtype < COUNTOF(ILArgumentOverrideProcs));
3487     return ILArgumentOverrideProcs[mtype];
3488 }
3489
3490 RETURNOVERRIDEPROC MarshalInfo::GetReturnOverrideProc(MarshalType mtype)
3491 {
3492     CONTRACTL
3493     {
3494         NOTHROW;
3495         GC_NOTRIGGER;
3496         MODE_ANY;
3497     }
3498     CONTRACTL_END;
3499     
3500     static const RETURNOVERRIDEPROC ILReturnOverrideProcs[] =
3501     {
3502         #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) IL##mclass::ReturnOverride,
3503         #include "mtypes.h"
3504     };
3505
3506     _ASSERTE((SIZE_T)mtype < COUNTOF(ILReturnOverrideProcs));
3507     return ILReturnOverrideProcs[mtype];
3508 }
3509
3510 void MarshalInfo::GetItfMarshalInfo(ItfMarshalInfo* pInfo)
3511 {
3512     STANDARD_VM_CONTRACT;
3513
3514     GetItfMarshalInfo(TypeHandle(m_pMT),
3515 #ifdef FEATURE_COMINTEROP
3516         TypeHandle(m_pDefaultItfMT),
3517 #else // FEATURE_COMINTEROP
3518         TypeHandle(),
3519 #endif // FEATURE_COMINTEROP
3520         m_fDispItf,
3521         m_fInspItf,
3522         m_ms,
3523         pInfo);
3524 }
3525
3526 void MarshalInfo::GetItfMarshalInfo(TypeHandle th, TypeHandle thItf, BOOL fDispItf, BOOL fInspItf, MarshalScenario ms, ItfMarshalInfo *pInfo)
3527 {
3528     CONTRACTL
3529     {
3530         THROWS;
3531         GC_TRIGGERS;
3532         MODE_ANY;
3533         PRECONDITION(CheckPointer(pInfo));
3534         PRECONDITION(!th.IsNull());
3535         PRECONDITION(!th.IsTypeDesc());
3536     }
3537     CONTRACTL_END;
3538
3539 #ifdef FEATURE_COMINTEROP
3540
3541     // Initialize the output parameter.
3542     pInfo->dwFlags = 0;
3543     pInfo->thItf = TypeHandle();
3544     pInfo->thClass = TypeHandle();
3545
3546     if (!th.IsInterface())
3547     {
3548         // If the parameter is not System.Object.
3549         if (!th.IsObjectType())
3550         {
3551             // Set the class method table.
3552             pInfo->thClass = th;
3553
3554             if (th.IsTypeDesc() || !th.AsMethodTable()->IsWinRTDelegate())
3555             {
3556                 // If this is not a WinRT delegate, retrieve the default interface method table.
3557                 TypeHandle hndDefItfClass;
3558                 DefaultInterfaceType DefItfType;
3559            
3560                 if (!thItf.IsNull())
3561                 {
3562                     hndDefItfClass = thItf;
3563                     DefItfType = DefaultInterfaceType_Explicit;
3564                 }
3565                 else if (th.IsProjectedFromWinRT() || th.IsExportedToWinRT())
3566                 {
3567                     // WinRT classes use their WinRT default interface
3568                     hndDefItfClass = th.GetMethodTable()->GetDefaultWinRTInterface();
3569                     DefItfType = DefaultInterfaceType_Explicit;
3570                 }
3571                 else
3572                 {
3573                     DefItfType = GetDefaultInterfaceForClassWrapper(th, &hndDefItfClass);
3574                 }
3575                 switch (DefItfType)
3576                 {
3577                     case DefaultInterfaceType_Explicit:
3578                     {
3579                         pInfo->thItf = hndDefItfClass;
3580                         switch (hndDefItfClass.GetComInterfaceType())
3581                         {
3582                             case ifDispatch:
3583                             case ifDual:
3584                                 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3585                                 break;
3586
3587                             case ifInspectable:
3588                                 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;
3589                                 break;
3590                         }
3591                         break;
3592                     }
3593
3594                     case DefaultInterfaceType_AutoDual:
3595                     {
3596                         pInfo->thItf = hndDefItfClass;
3597                         pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3598                         break;
3599                     }
3600
3601                     case DefaultInterfaceType_IUnknown:
3602                     case DefaultInterfaceType_BaseComClass:
3603                     {
3604                         break;
3605                     }
3606
3607                     case DefaultInterfaceType_AutoDispatch:
3608                     {
3609                         pInfo->thItf = hndDefItfClass;
3610                         pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3611                         break;
3612                     }
3613
3614                     default:
3615                     {
3616                         _ASSERTE(!"Invalid default interface type!");
3617                         break;
3618                     }
3619                 }
3620             }
3621         }
3622         else
3623         {
3624             // The type will be marshalled as an IUnknown, IInspectable, or IDispatch pointer depending
3625             // on the value of fDispItf and fInspItf
3626             if (fDispItf)
3627             {
3628                 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3629             }
3630             else if (fInspItf)
3631             {
3632                 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;
3633             }
3634             
3635             pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_USE_BASIC_ITF;
3636         }
3637     }
3638     else if (fInspItf)
3639     {
3640         // IInspectable-based interfaces are simple
3641         pInfo->thItf = th;
3642         pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;
3643     }
3644     else
3645     {
3646         // Determine the interface this type will be marshalled as. 
3647         if (th.IsComClassInterface())
3648             pInfo->thItf = th.GetDefItfForComClassItf();
3649         else
3650             pInfo->thItf = th;
3651
3652         // Determine if we are dealing with an IDispatch, IInspectable, or IUnknown based interface.
3653         switch (pInfo->thItf.GetComInterfaceType())
3654         {
3655             case ifDispatch:
3656             case ifDual:
3657                 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3658                 break;
3659
3660             case ifInspectable:
3661                 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;
3662                 break;
3663         }
3664
3665         // Look to see if the interface has a coclass defined
3666         pInfo->thClass = th.GetCoClassForInterface();
3667         if (!pInfo->thClass.IsNull())
3668         {
3669             pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_CLASS_IS_HINT;
3670         }
3671     }
3672
3673     // store the pre-redirection interface type as thNativeItf
3674     pInfo->thNativeItf = pInfo->thItf;
3675
3676     if (ms == MARSHAL_SCENARIO_WINRT)
3677     {
3678         // Use the "class is hint" flag so GetObjectRefFromComIP doesn't verify that the
3679         // WinRT object really supports IInspectable - note that we'll do the verification
3680         // in UnmarshalObjectFromInterface for this exact pInfo->thItf.
3681         pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_CLASS_IS_HINT;
3682
3683         pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_WINRT_SCENARIO;
3684         
3685         // Perform interface redirection statically here. When the resulting ItfMarshalInfo
3686         // is used for CLR->WinRT marshaling, this is necessary so we know which COM vtable
3687         // to pass out (for instance IList could be marshaled out as IList or IBindableVector
3688         // depending on the marshal scenario). In the WinRT->CLR direction, it's just an
3689         // optimization which saves us from performing redirection at run-time.
3690
3691         if (!pInfo->thItf.IsNull())
3692         {
3693             MethodTable *pNewItfMT1;
3694             MethodTable *pNewItfMT2;
3695             switch (RCW::GetInterfacesForQI(pInfo->thItf.GetMethodTable(), &pNewItfMT1, &pNewItfMT2))
3696             {
3697                 case RCW::InterfaceRedirection_None:
3698                 case RCW::InterfaceRedirection_UnresolvedIEnumerable:
3699                     break;
3700
3701                 case RCW::InterfaceRedirection_IEnumerable_RetryOnFailure:
3702                 case RCW::InterfaceRedirection_IEnumerable:
3703                 case RCW::InterfaceRedirection_Other:
3704                     pInfo->thNativeItf = pNewItfMT1;
3705                     break;
3706
3707                 case RCW::InterfaceRedirection_Other_RetryOnFailure:
3708                     pInfo->thNativeItf = pNewItfMT2;
3709                     break;
3710             }
3711         }
3712
3713         if (!pInfo->thNativeItf.IsNull())
3714         {
3715             // The native interface is redirected WinRT interface - need to change the flags
3716             _ASSERTE(pInfo->thNativeItf.AsMethodTable()->IsProjectedFromWinRT());
3717             
3718             pInfo->dwFlags &= ~ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3719             pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;            
3720         }
3721     }
3722
3723 #else // FEATURE_COMINTEROP
3724     if (!th.IsInterface())
3725         pInfo->thClass = th;
3726     else
3727         pInfo->thItf = th;
3728 #endif // FEATURE_COMINTEROP
3729 }
3730
3731 HRESULT MarshalInfo::TryGetItfMarshalInfo(TypeHandle th, BOOL fDispItf, BOOL fInspItf, ItfMarshalInfo *pInfo)
3732 {
3733     CONTRACTL
3734     {
3735         STANDARD_VM_CHECK;
3736         PRECONDITION(!th.IsNull());
3737         PRECONDITION(CheckPointer(pInfo));
3738     }
3739     CONTRACTL_END;
3740
3741     HRESULT hr = S_OK;
3742
3743     EX_TRY
3744     {
3745         GetItfMarshalInfo(th, TypeHandle(), fDispItf, fInspItf,
3746 #ifdef FEATURE_COMINTEROP
3747             MARSHAL_SCENARIO_COMINTEROP,
3748 #else // FEATURE_COMINTEROP
3749             MARSHAL_SCENARIO_NDIRECT,
3750 #endif // FEATURE_COMINTEROP
3751             pInfo);
3752     }
3753     EX_CATCH
3754     {
3755         hr = GET_EXCEPTION()->GetHR();
3756     }
3757     EX_END_CATCH(RethrowTerminalExceptions);
3758     
3759     return hr;
3760 }
3761
3762 #ifdef _DEBUG
3763 VOID MarshalInfo::DumpMarshalInfo(Module* pModule, SigPointer sig, const SigTypeContext *pTypeContext, mdToken token,
3764                                   MarshalScenario ms, CorNativeLinkType nlType, CorNativeLinkFlags nlFlags)
3765 {
3766     CONTRACTL
3767     {
3768         THROWS;
3769         GC_TRIGGERS;
3770         MODE_ANY;
3771     }
3772     CONTRACTL_END;
3773     
3774     if (LoggingOn(LF_MARSHALER, LL_INFO10))
3775     {
3776         SString logbuf;
3777         StackScratchBuffer scratch;
3778
3779         IMDInternalImport *pInternalImport = pModule->GetMDImport();
3780
3781         logbuf.AppendASCII("------------------------------------------------------------\n");
3782         LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch)));
3783         logbuf.Clear();
3784         
3785         logbuf.AppendASCII("Managed type: ");
3786         if (m_byref)
3787             logbuf.AppendASCII("Byref ");
3788
3789         TypeHandle th = sig.GetTypeHandleNT(pModule, pTypeContext);
3790         if (th.IsNull())
3791             logbuf.AppendASCII("<error>");
3792         else
3793         {
3794             SigFormat sigfmt;
3795             sigfmt.AddType(th);
3796             logbuf.AppendUTF8(sigfmt.GetCString());
3797         }
3798
3799         logbuf.AppendASCII("\n");
3800         LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch)));
3801         logbuf.Clear();
3802
3803         logbuf.AppendASCII("NativeType  : ");
3804         PCCOR_SIGNATURE pvNativeType;
3805         ULONG           cbNativeType;
3806         if (token == mdParamDefNil
3807             || pInternalImport->GetFieldMarshal(token,
3808                                                  &pvNativeType,
3809                                                  &cbNativeType) != S_OK)
3810         {
3811             logbuf.AppendASCII("<absent>");
3812         }
3813         else
3814         {
3815
3816             while (cbNativeType--)
3817             {
3818                 char num[100];
3819                 sprintf_s(num, COUNTOF(num), "0x%lx ", (ULONG)*pvNativeType);
3820                 logbuf.AppendASCII(num);
3821                 switch (*(pvNativeType++))
3822                 {
3823 #define XXXXX(nt) case nt: logbuf.AppendASCII("(" #nt ")"); break;
3824
3825                     XXXXX(NATIVE_TYPE_BOOLEAN)     
3826                     XXXXX(NATIVE_TYPE_I1)          
3827
3828                     XXXXX(NATIVE_TYPE_U1)
3829                     XXXXX(NATIVE_TYPE_I2)          
3830                     XXXXX(NATIVE_TYPE_U2)          
3831                     XXXXX(NATIVE_TYPE_I4)          
3832
3833                     XXXXX(NATIVE_TYPE_U4)
3834                     XXXXX(NATIVE_TYPE_I8)          
3835                     XXXXX(NATIVE_TYPE_U8)          
3836                     XXXXX(NATIVE_TYPE_R4)          
3837
3838                     XXXXX(NATIVE_TYPE_R8)
3839
3840                     XXXXX(NATIVE_TYPE_LPSTR)
3841                     XXXXX(NATIVE_TYPE_LPWSTR)      
3842                     XXXXX(NATIVE_TYPE_LPTSTR)      
3843                     XXXXX(NATIVE_TYPE_FIXEDSYSSTRING)
3844
3845                     XXXXX(NATIVE_TYPE_STRUCT)      
3846
3847                     XXXXX(NATIVE_TYPE_INT)         
3848                     XXXXX(NATIVE_TYPE_FIXEDARRAY)
3849
3850                     XXXXX(NATIVE_TYPE_UINT)
3851                 
3852                     XXXXX(NATIVE_TYPE_FUNC)
3853                 
3854                     XXXXX(NATIVE_TYPE_ASANY)
3855
3856                     XXXXX(NATIVE_TYPE_ARRAY)
3857                     XXXXX(NATIVE_TYPE_LPSTRUCT)
3858
3859                     XXXXX(NATIVE_TYPE_IUNKNOWN)
3860
3861                     XXXXX(NATIVE_TYPE_BSTR)
3862 #ifdef FEATURE_COMINTEROP
3863                     XXXXX(NATIVE_TYPE_TBSTR)
3864                     XXXXX(NATIVE_TYPE_ANSIBSTR)
3865                     XXXXX(NATIVE_TYPE_HSTRING)
3866                     XXXXX(NATIVE_TYPE_BYVALSTR)
3867
3868                     XXXXX(NATIVE_TYPE_VARIANTBOOL)
3869                     XXXXX(NATIVE_TYPE_SAFEARRAY)
3870
3871                     XXXXX(NATIVE_TYPE_IDISPATCH)
3872                     XXXXX(NATIVE_TYPE_INTF)
3873 #endif // FEATURE_COMINTEROP
3874
3875 #undef XXXXX
3876
3877                     
3878                     case NATIVE_TYPE_CUSTOMMARSHALER:
3879                     {
3880                         int strLen = 0;
3881                         logbuf.AppendASCII("(NATIVE_TYPE_CUSTOMMARSHALER)");
3882
3883                         // Skip the typelib guid.
3884                         logbuf.AppendASCII(" ");
3885
3886                         strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType);
3887                         if (strLen)
3888                         {
3889                             BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen);
3890                             memcpyNoGCRefs(p, pvNativeType, strLen);
3891                             logbuf.CloseBuffer();
3892                             logbuf.AppendASCII("\0");
3893
3894                             pvNativeType += strLen;
3895                             cbNativeType -= strLen + 1;
3896
3897                             // Skip the name of the native type.
3898                             logbuf.AppendASCII(" ");
3899                         }
3900                         
3901                         
3902                         strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType);
3903                         if (strLen)
3904                         {
3905                             BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen);
3906                             memcpyNoGCRefs(p, pvNativeType, strLen);
3907                             logbuf.CloseBuffer();
3908                             logbuf.AppendASCII("\0");
3909                             
3910                             pvNativeType += strLen;
3911                             cbNativeType -= strLen + 1;
3912                             
3913                             // Extract the name of the custom marshaler.
3914                             logbuf.AppendASCII(" ");
3915                         }
3916                         
3917                         
3918                         strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType);
3919                         if (strLen)
3920                         {
3921                             BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen);
3922                             memcpyNoGCRefs(p, pvNativeType, strLen);
3923                             logbuf.CloseBuffer();
3924                             logbuf.AppendASCII("\0");
3925                         
3926                             pvNativeType += strLen;
3927                             cbNativeType -= strLen + 1;
3928         
3929                             // Extract the cookie string.
3930                             logbuf.AppendASCII(" ");
3931                         }
3932                         
3933                         strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType);
3934                         if (strLen)
3935                         {
3936                             BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen);
3937                             memcpyNoGCRefs(p, pvNativeType, strLen);
3938                             logbuf.CloseBuffer();
3939                             logbuf.AppendASCII("\0");
3940
3941                             pvNativeType += strLen;
3942                             cbNativeType -= strLen + 1;
3943                         }
3944                         
3945                         break;
3946                     }
3947
3948                     default:
3949                         logbuf.AppendASCII("(?)");
3950                 }
3951
3952                 logbuf.AppendASCII("   ");
3953             }
3954         }
3955         logbuf.AppendASCII("\n");
3956         LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch)));
3957         logbuf.Clear();
3958
3959         logbuf.AppendASCII("MarshalType : ");
3960         {
3961             char num[100];
3962             sprintf_s(num, COUNTOF(num), "0x%lx ", (ULONG)m_type);
3963             logbuf.AppendASCII(num);
3964         }
3965         switch (m_type)
3966         {
3967             #define DEFINE_MARSHALER_TYPE(mt, mc, fWinRTSupported) case mt: logbuf.AppendASCII( #mt " (IL" #mc ")"); break;
3968             #include "mtypes.h"
3969
3970             case MARSHAL_TYPE_UNKNOWN:
3971                 logbuf.AppendASCII("MARSHAL_TYPE_UNKNOWN (illegal combination)");
3972                 break;
3973                 
3974             default:
3975                 logbuf.AppendASCII("MARSHAL_TYPE_???");
3976                 break;
3977         }
3978         
3979         logbuf.AppendASCII("\n");
3980         
3981         
3982         logbuf.AppendASCII("Metadata In/Out     : ");
3983         if (TypeFromToken(token) != mdtParamDef || token == mdParamDefNil)
3984             logbuf.AppendASCII("<absent>");
3985         
3986         else
3987         {
3988             DWORD dwAttr = 0;
3989             USHORT usSequence;
3990             LPCSTR szParamName_Ignore;
3991             if (FAILED(pInternalImport->GetParamDefProps(token, &usSequence, &dwAttr, &szParamName_Ignore)))
3992             {
3993                 logbuf.AppendASCII("Invalid ParamDef record ");
3994             }
3995             else
3996             {
3997                 if (IsPdIn(dwAttr))
3998                     logbuf.AppendASCII("In ");
3999                 
4000                 if (IsPdOut(dwAttr))
4001                     logbuf.AppendASCII("Out ");
4002             }
4003         }
4004         
4005         logbuf.AppendASCII("\n");
4006         
4007         logbuf.AppendASCII("Effective In/Out     : ");
4008         if (m_in)
4009             logbuf.AppendASCII("In ");
4010         
4011         if (m_out)
4012             logbuf.AppendASCII("Out ");
4013         
4014         logbuf.AppendASCII("\n");
4015         
4016         LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch)));
4017         logbuf.Clear();
4018     }
4019 } // MarshalInfo::DumpMarshalInfo
4020 #endif //_DEBUG
4021
4022 #ifndef CROSSGEN_COMPILE
4023 #ifdef FEATURE_COMINTEROP
4024 DispParamMarshaler *MarshalInfo::GenerateDispParamMarshaler()
4025 {
4026     CONTRACT (DispParamMarshaler*)
4027     {
4028         THROWS;
4029         GC_TRIGGERS;
4030         MODE_ANY;
4031         INJECT_FAULT(COMPlusThrowOM());
4032         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
4033     }
4034     CONTRACT_END;
4035
4036     NewHolder<DispParamMarshaler> pDispParamMarshaler = NULL;
4037
4038     switch (m_type)
4039     {
4040         case MARSHAL_TYPE_OLECOLOR:
4041             pDispParamMarshaler = new DispParamOleColorMarshaler();
4042             break;
4043
4044         case MARSHAL_TYPE_CURRENCY:
4045             pDispParamMarshaler = new DispParamCurrencyMarshaler();
4046             break;
4047
4048         case MARSHAL_TYPE_GENERIC_4:
4049             if (m_fErrorNativeType)
4050                 pDispParamMarshaler = new DispParamErrorMarshaler();
4051             break;
4052
4053         case MARSHAL_TYPE_INTERFACE:
4054         {
4055             ItfMarshalInfo itfInfo;
4056             GetItfMarshalInfo(TypeHandle(m_pMT), TypeHandle(m_pDefaultItfMT), m_fDispItf, m_fInspItf, m_ms, &itfInfo);
4057             pDispParamMarshaler = new DispParamInterfaceMarshaler(
4058                 itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF, 
4059                 itfInfo.thItf.GetMethodTable(), 
4060                 itfInfo.thClass.GetMethodTable(), 
4061                 itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_CLASS_IS_HINT);
4062             break;
4063         }
4064
4065         case MARSHAL_TYPE_VALUECLASS:
4066         case MARSHAL_TYPE_BLITTABLEVALUECLASS:
4067         case MARSHAL_TYPE_BLITTABLEPTR:
4068         case MARSHAL_TYPE_LAYOUTCLASSPTR:
4069             pDispParamMarshaler = new DispParamRecordMarshaler(m_pMT);
4070             break;
4071
4072 #ifdef FEATURE_CLASSIC_COMINTEROP
4073         case MARSHAL_TYPE_SAFEARRAY:
4074             pDispParamMarshaler = new DispParamArrayMarshaler(m_arrayElementType, m_hndArrayElemType.GetMethodTable());
4075             break;
4076 #endif
4077
4078         case MARSHAL_TYPE_DELEGATE:
4079             pDispParamMarshaler = new DispParamDelegateMarshaler(m_pMT);
4080             break;
4081             
4082         case MARSHAL_TYPE_REFERENCECUSTOMMARSHALER:
4083             pDispParamMarshaler = new DispParamCustomMarshaler(m_pCMHelper, m_CMVt);
4084             break;
4085     }
4086
4087     pDispParamMarshaler.SuppressRelease();
4088     RETURN pDispParamMarshaler;
4089 }
4090
4091
4092 DispatchWrapperType MarshalInfo::GetDispWrapperType()
4093 {
4094     STANDARD_VM_CONTRACT;
4095     
4096     DispatchWrapperType WrapperType = (DispatchWrapperType)0;
4097
4098     switch (m_type)
4099     {
4100         case MARSHAL_TYPE_CURRENCY:
4101             WrapperType = DispatchWrapperType_Currency;
4102             break;
4103
4104         case MARSHAL_TYPE_BSTR:
4105             WrapperType = DispatchWrapperType_BStr;
4106             break;
4107
4108         case MARSHAL_TYPE_GENERIC_4:
4109             if (m_fErrorNativeType)
4110                 WrapperType = DispatchWrapperType_Error;
4111             break;
4112
4113         case MARSHAL_TYPE_INTERFACE:
4114         {
4115             ItfMarshalInfo itfInfo;
4116             GetItfMarshalInfo(TypeHandle(m_pMT), TypeHandle(m_pDefaultItfMT), m_fDispItf, m_fInspItf, m_ms, &itfInfo);
4117             WrapperType = !!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF) ? DispatchWrapperType_Dispatch : DispatchWrapperType_Unknown;
4118             break;
4119         }
4120     
4121         case MARSHAL_TYPE_SAFEARRAY:
4122             switch (m_arrayElementType)
4123             {
4124                 case VT_CY:
4125                     WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_Currency);
4126                     break;
4127                 case VT_UNKNOWN:
4128                     WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_Unknown);
4129                     break;
4130                 case VT_DISPATCH:
4131                     WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_Dispatch);
4132                     break;
4133                 case VT_ERROR:
4134                     WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_Error);
4135                     break;
4136                 case VT_BSTR:
4137                     WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_BStr);
4138                     break;
4139             }
4140             break;
4141     }
4142
4143     return WrapperType;
4144 }
4145
4146 #endif // FEATURE_COMINTEROP
4147
4148
4149 VOID MarshalInfo::MarshalTypeToString(SString& strMarshalType, BOOL fSizeIsSpecified)
4150 {
4151     CONTRACTL
4152     {
4153         THROWS;
4154         GC_TRIGGERS;
4155         MODE_ANY;
4156     }
4157     CONTRACTL_END;
4158     
4159     LPCWSTR strRetVal;
4160
4161     if (m_type == MARSHAL_TYPE_NATIVEARRAY)
4162     {
4163         SString strVarType;
4164         VarTypeToString(m_arrayElementType, strVarType);
4165
4166         if (!fSizeIsSpecified)
4167         {
4168             strMarshalType.Printf(W("native array of %s (size not specified by a parameter)"),
4169                                   strVarType.GetUnicode());
4170         }
4171         else
4172         {
4173             strMarshalType.Printf(W("native array of %s (size specified by parameter %i)"),
4174                                   strVarType.GetUnicode(), m_countParamIdx);
4175         }
4176
4177         return;
4178     }
4179 #ifdef FEATURE_COMINTEROP
4180     // Some MarshalTypes have extra information and require special handling
4181     else if (m_type == MARSHAL_TYPE_INTERFACE)
4182     {
4183         ItfMarshalInfo itfInfo;
4184         GetItfMarshalInfo(TypeHandle(m_pMT), TypeHandle(m_pDefaultItfMT), m_fDispItf, m_fInspItf, m_ms, &itfInfo);
4185
4186         if (!itfInfo.thItf.IsNull())
4187         {
4188             StackSString ssClassName;
4189             itfInfo.thItf.GetMethodTable()->_GetFullyQualifiedNameForClass(ssClassName);
4190
4191             if (!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF))
4192             {
4193                 strMarshalType.SetLiteral(W("IDispatch "));
4194             }
4195             else if (!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_INSP_ITF))
4196             {
4197                 strMarshalType.SetLiteral(W("IInspectable"));
4198             }
4199             else
4200             {
4201                 strMarshalType.SetLiteral(W("IUnknown "));
4202             }
4203
4204             if (itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_USE_BASIC_ITF)
4205             {
4206                 strMarshalType.Append(W("(basic) "));
4207             }
4208
4209             strMarshalType.Append(ssClassName);
4210             return;
4211         }
4212         else
4213         {
4214             if (!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF))
4215                 strRetVal = W("IDispatch");
4216             else if (!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_INSP_ITF))
4217                 strRetVal = W("IInspectable");
4218             else
4219                 strRetVal = W("IUnknown");
4220         }
4221     }
4222     else if (m_type == MARSHAL_TYPE_SAFEARRAY)
4223     {
4224         StackSString strVarType;
4225         VarTypeToString(m_arrayElementType, strVarType);
4226
4227         strMarshalType = SL(W("SafeArray of "));
4228         strMarshalType.Append(strVarType);
4229
4230         return;
4231     }
4232 #endif // FEATURE_COMINTEROP
4233     else if (m_type == MARSHAL_TYPE_REFERENCECUSTOMMARSHALER)
4234     {
4235         GCX_COOP();
4236         
4237         OBJECTHANDLE objHandle = m_pCMHelper->GetCustomMarshalerInfo()->GetCustomMarshaler();
4238         {
4239             OBJECTREF pObjRef = ObjectFromHandle(objHandle);
4240             DefineFullyQualifiedNameForClassW();
4241
4242             strMarshalType.Printf(W("custom marshaler (%s)"),
4243                                   GetFullyQualifiedNameForClassW(pObjRef->GetMethodTable()));
4244         }        
4245         
4246         return;
4247     }
4248     else
4249     {
4250         // All other MarshalTypes with no special handling
4251         switch (m_type)
4252         {
4253             case MARSHAL_TYPE_GENERIC_1:
4254                 strRetVal = W("BYTE");
4255                 break;
4256             case MARSHAL_TYPE_GENERIC_U1:
4257                 strRetVal = W("unsigned BYTE");
4258                 break;
4259             case MARSHAL_TYPE_GENERIC_2:
4260                 strRetVal = W("WORD");
4261                 break;
4262             case MARSHAL_TYPE_GENERIC_U2:
4263                 strRetVal = W("unsigned WORD");
4264                 break;
4265             case MARSHAL_TYPE_GENERIC_4:
4266                 strRetVal = W("DWORD");
4267                 break;
4268             case MARSHAL_TYPE_GENERIC_8:
4269                 strRetVal = W("QUADWORD");
4270                 break;
4271             case MARSHAL_TYPE_WINBOOL:
4272                 strRetVal = W("Windows Bool");
4273                 break;
4274 #ifdef FEATURE_COMINTEROP
4275             case MARSHAL_TYPE_VTBOOL:
4276                 strRetVal = W("VARIANT Bool");
4277                 break;
4278 #endif // FEATURE_COMINTEROP
4279             case MARSHAL_TYPE_ANSICHAR:
4280                 strRetVal = W("Ansi character");
4281                 break;
4282             case MARSHAL_TYPE_CBOOL:
4283                 strRetVal = W("CBool");
4284                 break;
4285             case MARSHAL_TYPE_FLOAT:
4286                 strRetVal = W("float");
4287                 break;
4288             case MARSHAL_TYPE_DOUBLE:
4289                 strRetVal = W("double");
4290                 break;
4291             case MARSHAL_TYPE_CURRENCY:
4292                 strRetVal = W("CURRENCY");
4293                 break;
4294             case MARSHAL_TYPE_DECIMAL:
4295                 strRetVal = W("DECIMAL");
4296                 break;
4297             case MARSHAL_TYPE_DECIMAL_PTR:
4298                 strRetVal = W("DECIMAL pointer");
4299                 break;
4300             case MARSHAL_TYPE_GUID:
4301                 strRetVal = W("GUID");
4302                 break;
4303             case MARSHAL_TYPE_GUID_PTR:
4304                 strRetVal = W("GUID pointer");
4305                 break;
4306             case MARSHAL_TYPE_DATE:
4307                 strRetVal = W("DATE");
4308                 break;
4309              case MARSHAL_TYPE_BSTR:
4310                 strRetVal = W("BSTR");
4311                 break;
4312             case MARSHAL_TYPE_LPWSTR:
4313                 strRetVal = W("LPWSTR");
4314                 break;
4315             case MARSHAL_TYPE_LPSTR:
4316                 strRetVal = W("LPSTR");
4317                 break;
4318             case MARSHAL_TYPE_LPUTF8STR:
4319                 strRetVal = W("LPUTF8STR");
4320                 break;
4321 #ifdef FEATURE_COMINTEROP
4322             case MARSHAL_TYPE_ANSIBSTR:
4323                 strRetVal = W("AnsiBStr");
4324                 break;
4325 #endif // FEATURE_COMINTEROP
4326             case MARSHAL_TYPE_LPWSTR_BUFFER:
4327                 strRetVal = W("LPWSTR buffer");
4328                 break;
4329             case MARSHAL_TYPE_LPSTR_BUFFER:
4330                 strRetVal = W("LPSTR buffer");
4331                 break;
4332             case MARSHAL_TYPE_UTF8_BUFFER:
4333                 strRetVal = W("UTF8 buffer");
4334                 break;
4335             case MARSHAL_TYPE_ASANYA:
4336                 strRetVal = W("AsAnyA");
4337                 break;
4338             case MARSHAL_TYPE_ASANYW:
4339                 strRetVal = W("AsAnyW");
4340                 break;
4341             case MARSHAL_TYPE_DELEGATE:
4342                 strRetVal = W("Delegate");
4343                 break;
4344             case MARSHAL_TYPE_BLITTABLEPTR:
4345                 strRetVal = W("blittable pointer");
4346                 break;
4347 #ifdef FEATURE_COMINTEROP
4348             case MARSHAL_TYPE_VBBYVALSTR:
4349                 strRetVal = W("VBByValStr");
4350                 break;
4351             case MARSHAL_TYPE_VBBYVALSTRW:
4352                 strRetVal = W("VBByRefStr");
4353                 break;
4354 #endif // FEATURE_COMINTEROP
4355             case MARSHAL_TYPE_LAYOUTCLASSPTR:
4356                 strRetVal = W("Layout class pointer");
4357                 break;
4358             case MARSHAL_TYPE_ARRAYWITHOFFSET:
4359                 strRetVal = W("ArrayWithOffset");
4360                 break;
4361             case MARSHAL_TYPE_BLITTABLEVALUECLASS:
4362                 strRetVal = W("blittable value class");
4363                 break;
4364             case MARSHAL_TYPE_VALUECLASS:
4365                 strRetVal = W("value class");
4366                 break;
4367             case MARSHAL_TYPE_ARGITERATOR:
4368                 strRetVal = W("ArgIterator");
4369                 break;
4370 #ifdef FEATURE_COMINTEROP
4371             case MARSHAL_TYPE_OBJECT:
4372                 strRetVal = W("VARIANT");
4373                 break;
4374 #endif // FEATURE_COMINTEROP
4375             case MARSHAL_TYPE_HANDLEREF:
4376                 strRetVal = W("HandleRef");
4377                 break;
4378 #ifdef FEATURE_COMINTEROP
4379             case MARSHAL_TYPE_OLECOLOR:
4380                 strRetVal = W("OLE_COLOR");
4381                 break;
4382 #endif // FEATURE_COMINTEROP
4383             case MARSHAL_TYPE_RUNTIMETYPEHANDLE:
4384                 strRetVal = W("RuntimeTypeHandle");
4385                 break;
4386             case MARSHAL_TYPE_RUNTIMEFIELDHANDLE:
4387                 strRetVal = W("RuntimeFieldHandle");
4388                 break;
4389             case MARSHAL_TYPE_RUNTIMEMETHODHANDLE:
4390                 strRetVal = W("RuntimeMethodHandle");
4391                 break;
4392             case MARSHAL_TYPE_RUNTIMEMETHODINFO:
4393                 strRetVal = W("RuntimeMethodInfo");
4394                 break;
4395             case MARSHAL_TYPE_RUNTIMEMODULE:
4396                 strRetVal = W("RuntimeModule");
4397                 break;
4398             case MARSHAL_TYPE_RUNTIMEASSEMBLY:
4399                 strRetVal = W("RuntimeAssembly");
4400                 break;
4401             default:
4402                 strRetVal = W("<UNKNOWN>");
4403                 break;
4404         }
4405     }
4406
4407     strMarshalType.Set(strRetVal);
4408     return;
4409 }
4410
4411 VOID MarshalInfo::VarTypeToString(VARTYPE vt, SString& strVarType)
4412 {
4413     CONTRACTL
4414     {
4415         THROWS;
4416         GC_NOTRIGGER;
4417         MODE_ANY;
4418     }
4419     CONTRACTL_END;
4420
4421     
4422     LPCWSTR strRetVal;
4423     
4424     switch(vt)
4425     {
4426         case VT_I2:
4427             strRetVal = W("2-byte signed int");
4428             break;
4429         case VT_I4:
4430             strRetVal = W("4-byte signed int");
4431             break;
4432         case VT_R4:
4433             strRetVal = W("4-byte real");
4434             break;
4435         case VT_R8:
4436             strRetVal = W("8-byte real");
4437             break;
4438         case VT_CY:
4439             strRetVal = W("currency");
4440             break;
4441         case VT_DATE:
4442             strRetVal = W("date");
4443             break;
4444         case VT_BSTR:
4445             strRetVal = W("binary string");
4446             break;
4447         case VT_DISPATCH:
4448             strRetVal = W("IDispatch *");
4449             break;
4450         case VT_ERROR:
4451             strRetVal = W("Scode");
4452             break;
4453         case VT_BOOL:
4454             strRetVal = W("boolean");
4455             break;
4456         case VT_VARIANT:
4457             strRetVal = W("VARIANT *");
4458             break;
4459         case VT_UNKNOWN:
4460             strRetVal = W("IUnknown *");
4461             break;
4462         case VT_DECIMAL:
4463             strRetVal = W("16-byte fixed point");
4464             break;
4465         case VT_RECORD:
4466             strRetVal = W("user defined structure");
4467             break;
4468         case VT_I1:
4469             strRetVal = W("signed char");
4470             break;
4471         case VT_UI1:
4472             strRetVal = W("unsigned char");
4473             break;
4474         case VT_UI2:
4475             strRetVal = W("unsigned short");
4476             break;
4477         case VT_UI4:
4478             strRetVal = W("unsigned short");
4479             break;
4480         case VT_INT:
4481             strRetVal = W("signed int");
4482             break;
4483         case VT_UINT:
4484             strRetVal = W("unsigned int");
4485             break;
4486         case VT_LPSTR:
4487             strRetVal = W("LPSTR");
4488             break;
4489         case VT_LPWSTR:
4490             strRetVal = W("LPWSTR");
4491             break;
4492         case VT_HRESULT:
4493             strRetVal = W("HResult");
4494             break;
4495         case VT_I8:
4496             strRetVal = W("8-byte signed int");
4497             break;
4498         case VT_NULL:
4499             strRetVal = W("null");
4500             break;
4501         case VT_UI8:
4502             strRetVal = W("8-byte unsigned int");
4503             break;
4504         case VT_VOID:
4505             strRetVal = W("void");
4506             break;
4507         case VTHACK_WINBOOL:
4508             strRetVal = W("boolean");
4509             break;
4510         case VTHACK_ANSICHAR:
4511             strRetVal = W("char");
4512             break;
4513         case VTHACK_CBOOL:
4514             strRetVal = W("1-byte C bool");
4515             break;
4516         default:
4517             strRetVal = W("unknown");
4518             break;
4519     }
4520
4521     strVarType.Set(strRetVal);    
4522     return;
4523 }
4524
4525 #endif // CROSSGEN_COMPILE
4526
4527 // Returns true if the marshaler represented by this instance requires COM to have been started.
4528 bool MarshalInfo::MarshalerRequiresCOM()
4529 {
4530     LIMITED_METHOD_CONTRACT;
4531
4532 #ifdef FEATURE_COMINTEROP
4533     switch (m_type)
4534     {
4535         case MARSHAL_TYPE_REFERENCECUSTOMMARSHALER:
4536
4537         case MARSHAL_TYPE_BSTR:
4538         case MARSHAL_TYPE_ANSIBSTR:
4539         case MARSHAL_TYPE_OBJECT:
4540         case MARSHAL_TYPE_OLECOLOR:
4541         case MARSHAL_TYPE_SAFEARRAY:
4542         case MARSHAL_TYPE_INTERFACE:
4543
4544         case MARSHAL_TYPE_URI:
4545         case MARSHAL_TYPE_KEYVALUEPAIR:
4546         case MARSHAL_TYPE_NULLABLE:
4547         case MARSHAL_TYPE_SYSTEMTYPE:
4548         case MARSHAL_TYPE_EXCEPTION:
4549         case MARSHAL_TYPE_HIDDENLENGTHARRAY:
4550         case MARSHAL_TYPE_HSTRING:
4551         case MARSHAL_TYPE_NCCEVENTARGS:
4552         case MARSHAL_TYPE_PCEVENTARGS:
4553         {
4554             // some of these types do not strictly require COM for the actual marshaling
4555             // but they tend to be used in COM context so we keep the logic we had in
4556             // previous versions and return true here
4557             return true;
4558         }
4559         
4560         case MARSHAL_TYPE_LAYOUTCLASSPTR:
4561         case MARSHAL_TYPE_VALUECLASS:
4562         {
4563             // pessimistic guess, but in line with previous versions            
4564             return true;
4565         }
4566
4567         case MARSHAL_TYPE_NATIVEARRAY:
4568         {
4569             return (m_arrayElementType == VT_UNKNOWN ||
4570                     m_arrayElementType == VT_DISPATCH ||
4571                     m_arrayElementType == VT_VARIANT);
4572         }
4573     }
4574 #endif // FEATURE_COMINTEROP
4575
4576     return false;
4577 }
4578
4579 #ifdef FEATURE_COMINTEROP
4580 MarshalInfo::MarshalType MarshalInfo::GetHiddenLengthParamMarshalType()
4581 {
4582     LIMITED_METHOD_CONTRACT;
4583     return MARSHAL_TYPE_GENERIC_U4;
4584 }
4585
4586 CorElementType MarshalInfo::GetHiddenLengthParamElementType()
4587 {
4588     LIMITED_METHOD_CONTRACT;
4589     return ELEMENT_TYPE_U4;
4590 }
4591
4592 UINT16 MarshalInfo::GetHiddenLengthParamStackSize()
4593 {
4594     LIMITED_METHOD_CONTRACT;
4595     return StackElemSize(GetNativeSize(GetHiddenLengthParamMarshalType(), m_ms));
4596 }
4597
4598 void MarshalInfo::MarshalHiddenLengthArgument(NDirectStubLinker *psl, BOOL managedToNative, BOOL isForReturnArray)
4599 {
4600     CONTRACTL
4601     {
4602         STANDARD_VM_CHECK;
4603         PRECONDITION(CheckPointer(psl));
4604         PRECONDITION(m_type == MARSHAL_TYPE_HIDDENLENGTHARRAY);
4605         PRECONDITION(m_dwHiddenLengthManagedHomeLocal == 0xFFFFFFFF);
4606         PRECONDITION(m_dwHiddenLengthNativeHomeLocal == 0xFFFFFFFF);
4607     }
4608     CONTRACTL_END;
4609         
4610     NewHolder<ILMarshaler> pHiddenLengthMarshaler = CreateILMarshaler(GetHiddenLengthParamMarshalType(), psl);
4611
4612
4613     ILCodeStream *pcsMarshal = psl->GetMarshalCodeStream();
4614     ILCodeStream *pcsUnmarshal = psl->GetUnmarshalCodeStream();
4615
4616     pcsMarshal->EmitNOP("// hidden length argument { ");
4617     pcsUnmarshal->EmitNOP("// hidden length argument { ");
4618
4619     DWORD dwMarshalFlags = MARSHAL_FLAG_HIDDENLENPARAM;
4620     if (isForReturnArray)
4621     {
4622         // This is a hidden length argument for an [out, retval] argument, so setup flags to match that
4623         dwMarshalFlags |= CalculateArgumentMarshalFlags(TRUE, FALSE, TRUE, managedToNative);
4624     }
4625     else
4626     {
4627         // The length parameter needs to be an [in] parameter if the array itself is an [in] parameter.
4628         // Additionally, in order to support the FillArray pattern:
4629         //   FillArray([in] UInt32 length, [out, size_is(length)] ElementType* value)
4630         //
4631         // We need to make sure that the length parameter is [in] if the array pointer is not byref, since
4632         // this means that the caller is allocating the array.  This includes array buffers which are [out]
4633         // but not byref, since the [out] marshaling applies to the array contents but not the array pointer
4634         // value itself.
4635         BOOL marshalHiddenLengthIn = m_in || !m_byref;
4636         dwMarshalFlags |= CalculateArgumentMarshalFlags(m_byref, marshalHiddenLengthIn, m_out, managedToNative);
4637     }
4638     pHiddenLengthMarshaler->EmitMarshalHiddenLengthArgument(pcsMarshal,
4639                                                             pcsUnmarshal,
4640                                                             this,
4641                                                             m_paramidx,
4642                                                             dwMarshalFlags,
4643                                                             HiddenLengthParamIndex(),
4644                                                             &m_args,
4645                                                             &m_dwHiddenLengthManagedHomeLocal,
4646                                                             &m_dwHiddenLengthNativeHomeLocal);
4647
4648     pcsMarshal->EmitNOP("// } hidden length argument");
4649     pcsUnmarshal->EmitNOP("// } hidden length argument");
4650
4651     // Only emit into the dispatch stream for CLR -> Native cases - in the reverse, there is no argument
4652     // to pass to the managed method.  Instead, the length is encoded in the marshaled array.
4653     if (managedToNative)
4654     {
4655         ILCodeStream* pcsDispatch = psl->GetDispatchCodeStream();
4656         pHiddenLengthMarshaler->EmitSetupArgument(pcsDispatch);
4657     }
4658 }
4659
4660 #endif // FEATURE_COMINTEROP
4661
4662 #define ReportInvalidArrayMarshalInfo(resId)    \
4663     do                                          \
4664     {                                           \
4665         m_vtElement = VT_EMPTY;                 \
4666         m_errorResourceId = resId;              \
4667         m_thElement = TypeHandle();             \
4668         goto LExit;                             \
4669     }                                           \
4670     while (0)                                   
4671
4672 void ArrayMarshalInfo::InitForNativeArray(MarshalInfo::MarshalScenario ms, TypeHandle thElement, CorNativeType ntElement, BOOL isAnsi)
4673 {
4674     WRAPPER_NO_CONTRACT;        
4675     InitElementInfo(NATIVE_TYPE_ARRAY, ms, thElement, ntElement, isAnsi);
4676 }
4677
4678 void ArrayMarshalInfo::InitForFixedArray(TypeHandle thElement, CorNativeType ntElement, BOOL isAnsi)
4679 {
4680     WRAPPER_NO_CONTRACT;        
4681     InitElementInfo(NATIVE_TYPE_FIXEDARRAY, MarshalInfo::MARSHAL_SCENARIO_FIELD, thElement, ntElement, isAnsi);
4682 }
4683
4684 #ifdef FEATURE_COMINTEROP    
4685 void ArrayMarshalInfo::InitForSafeArray(MarshalInfo::MarshalScenario ms, TypeHandle thElement, VARTYPE vtElement, BOOL isAnsi)
4686 {
4687     STANDARD_VM_CONTRACT;
4688     
4689     InitElementInfo(NATIVE_TYPE_SAFEARRAY, ms, thElement, NATIVE_TYPE_DEFAULT, isAnsi);
4690
4691     if (IsValid() && vtElement != VT_EMPTY)
4692     {
4693         if (vtElement == VT_USERDEFINED)
4694         {
4695             // If the user explicitly sets the VARTYPE to VT_USERDEFINED, we simply ignore it 
4696             // since the exporter will take care of transforming the vt to VT_USERDEFINED and the 
4697             // marshallers needs the actual type.
4698         }
4699         else
4700         {
4701             m_flags = (ArrayMarshalInfoFlags)(m_flags | amiSafeArraySubTypeExplicitlySpecified);
4702             m_vtElement = vtElement;
4703         }
4704     }
4705 }
4706
4707 void ArrayMarshalInfo::InitForHiddenLengthArray(TypeHandle thElement)
4708 {
4709     STANDARD_VM_CONTRACT;
4710     
4711     MethodTable *pMT = NULL;
4712
4713     // WinRT supports arrays of any WinRT-legal types
4714     if (thElement.IsArray())
4715     {
4716         ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_NESTEDARRAY);
4717     }
4718     else if (thElement.IsTypeDesc() || !thElement.GetMethodTable()->IsLegalNonArrayWinRTType())
4719     {
4720         ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE);
4721     }
4722
4723     m_thElement = thElement;
4724
4725     pMT = thElement.GetMethodTable();
4726     if (pMT->IsString())
4727     {
4728         m_vtElement = VTHACK_HSTRING;
4729         m_cbElementSize = sizeof(HSTRING);
4730     }
4731     else if (WinRTTypeNameConverter::ResolveRedirectedType(pMT, &m_redirectedTypeIndex))
4732     {
4733         m_vtElement = VTHACK_REDIRECTEDTYPE;
4734
4735         switch (m_redirectedTypeIndex)
4736         {
4737             case WinMDAdapter::RedirectedTypeIndex_System_DateTimeOffset:
4738                 m_cbElementSize = ILDateTimeMarshaler::c_nativeSize;
4739                 break;
4740
4741             case WinMDAdapter::RedirectedTypeIndex_System_Type:
4742                 m_cbElementSize = ILSystemTypeMarshaler::c_nativeSize;
4743                 break;
4744
4745             case WinMDAdapter::RedirectedTypeIndex_System_Exception:
4746                 m_cbElementSize = ILHResultExceptionMarshaler::c_nativeSize;
4747                 break;
4748
4749                 // WinRT delegates are IUnknown pointers
4750             case WinMDAdapter::RedirectedTypeIndex_System_EventHandlerGeneric:
4751                 m_vtElement = VTHACK_INSPECTABLE;
4752                 m_cbElementSize = sizeof(IUnknown*);
4753                 break;
4754
4755             case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_KeyValuePair:
4756             case WinMDAdapter::RedirectedTypeIndex_System_Nullable:
4757             case WinMDAdapter::RedirectedTypeIndex_System_Uri:
4758             case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
4759             case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
4760             {
4761                 m_cbElementSize = sizeof(IInspectable *);
4762                 break;
4763             }
4764
4765             default:
4766             {
4767                 if (pMT->IsValueType())
4768                 {
4769                     // other redirected structs are blittable and don't need special marshaling
4770                     m_vtElement = VTHACK_BLITTABLERECORD;
4771                     m_cbElementSize = pMT->GetNativeSize();
4772                 }
4773                 else
4774                 {
4775                     // redirected interfaces should be treated as interface pointers
4776                     _ASSERTE(pMT->IsInterface());
4777                     m_vtElement = VTHACK_INSPECTABLE;
4778                     m_cbElementSize = sizeof(IInspectable *);
4779                 }
4780                 break;
4781             }
4782         }
4783     }
4784     else if (pMT->IsBlittable() || pMT->IsTruePrimitive() || pMT->IsEnum())
4785     {
4786         m_vtElement = VTHACK_BLITTABLERECORD;
4787
4788         CorElementType elemType = pMT->GetInternalCorElementType();
4789         if (CorTypeInfo::IsPrimitiveType(elemType))
4790         {
4791             // .NET and WinRT primitives have the same size
4792             m_cbElementSize = CorTypeInfo::Size(elemType);
4793         }
4794         else
4795         {
4796             m_cbElementSize = pMT->GetNativeSize();
4797         }
4798     }
4799     else if (pMT->IsValueType())
4800     {
4801         m_vtElement = VTHACK_NONBLITTABLERECORD;
4802         m_cbElementSize = pMT->GetNativeSize();
4803     }
4804     else
4805     {
4806         m_vtElement = VTHACK_INSPECTABLE;
4807         m_cbElementSize = sizeof(IInspectable *);
4808     }
4809
4810 LExit:;
4811 }
4812 #endif // FEATURE_COMINTEROP
4813
4814 void ArrayMarshalInfo::InitElementInfo(CorNativeType arrayNativeType, MarshalInfo::MarshalScenario ms, TypeHandle thElement, CorNativeType ntElement, BOOL isAnsi)
4815 {
4816     CONTRACT_VOID
4817     {
4818         STANDARD_VM_CHECK;
4819         PRECONDITION(!thElement.IsNull());
4820         POSTCONDITION(!IsValid() || !m_thElement.IsNull());
4821     }
4822     CONTRACT_END;
4823
4824     CorElementType etElement = ELEMENT_TYPE_END;    
4825     
4826     //
4827     // IMPORTANT: The error resource IDs used in this function must not contain any placeholders!
4828     // 
4829     // Also please maintain the standard of using IDS_EE_BADMARSHAL_XXX when defining new error
4830     // message resource IDs.
4831     //
4832
4833     if (thElement.IsArray())
4834         ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_NESTEDARRAY);
4835
4836     m_thElement = thElement;
4837
4838     if (m_thElement.IsPointer())
4839     {
4840         m_flags = (ArrayMarshalInfoFlags)(m_flags | amiIsPtr);
4841         m_thElement = ((ParamTypeDesc*)m_thElement.AsTypeDesc())->GetModifiedType();
4842     }
4843     
4844     etElement = m_thElement.GetSignatureCorElementType();
4845
4846     if (IsAMIPtr(m_flags) && (etElement > ELEMENT_TYPE_R8))
4847     {
4848         ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_UNSUPPORTED_SIG);        
4849     }
4850
4851     if (etElement == ELEMENT_TYPE_CHAR)
4852     {
4853         switch (ntElement)
4854         {
4855             case NATIVE_TYPE_I1: //fallthru
4856             case NATIVE_TYPE_U1:
4857                 m_vtElement = VTHACK_ANSICHAR;
4858                 break;
4859
4860             case NATIVE_TYPE_I2: //fallthru
4861             case NATIVE_TYPE_U2:
4862                 m_vtElement = VT_UI2;
4863                 break;
4864
4865             // Compat: If the native type doesn't make sense, we need to ignore it and not report an error.
4866             case NATIVE_TYPE_DEFAULT: //fallthru
4867             default:
4868 #ifdef FEATURE_COMINTEROP                
4869                 if (ms == MarshalInfo::MARSHAL_SCENARIO_COMINTEROP)
4870                     m_vtElement = VT_UI2;
4871                 else
4872 #endif // FEATURE_COMINTEROP
4873                     m_vtElement = isAnsi ? VTHACK_ANSICHAR : VT_UI2;                    
4874         }
4875     }
4876     else if (etElement == ELEMENT_TYPE_BOOLEAN)
4877     {
4878         switch (ntElement)
4879         {
4880             case NATIVE_TYPE_BOOLEAN:
4881                 m_vtElement = VTHACK_WINBOOL;
4882                 break;
4883
4884 #ifdef FEATURE_COMINTEROP
4885             case NATIVE_TYPE_VARIANTBOOL:
4886                 m_vtElement = VT_BOOL;
4887                 break;
4888 #endif // FEATURE_COMINTEROP
4889
4890             case NATIVE_TYPE_I1 :
4891             case NATIVE_TYPE_U1 :
4892                 m_vtElement = VTHACK_CBOOL;
4893                 break;
4894                 
4895             // Compat: if the native type doesn't make sense, we need to ignore it and not report an error.
4896             case NATIVE_TYPE_DEFAULT: //fallthru
4897             default:
4898 #ifdef FEATURE_COMINTEROP
4899                 if (ms == MarshalInfo::MARSHAL_SCENARIO_COMINTEROP ||
4900                     arrayNativeType == NATIVE_TYPE_SAFEARRAY)
4901                 {
4902                     m_vtElement = VT_BOOL;            
4903                 }
4904                 else
4905 #endif // FEATURE_COMINTEROP
4906                 {
4907                     m_vtElement = VTHACK_WINBOOL;
4908                 }
4909                 break;
4910         }                
4911     }
4912     else if (etElement == ELEMENT_TYPE_I)
4913     {
4914         m_vtElement = static_cast<VARTYPE>((GetPointerSize() == 4) ? VT_I4 : VT_I8);
4915     }
4916     else if (etElement == ELEMENT_TYPE_U)
4917     {
4918         m_vtElement = static_cast<VARTYPE>((GetPointerSize() == 4) ? VT_UI4 : VT_UI8);
4919     }
4920     else if (etElement <= ELEMENT_TYPE_R8)
4921     {
4922         static const BYTE map [] =
4923         {
4924             VT_NULL,    // ELEMENT_TYPE_END
4925             VT_VOID,    // ELEMENT_TYPE_VOID
4926             VT_NULL,    // ELEMENT_TYPE_BOOLEAN
4927             VT_NULL,    // ELEMENT_TYPE_CHAR
4928             VT_I1,      // ELEMENT_TYPE_I1
4929             VT_UI1,     // ELEMENT_TYPE_U1
4930             VT_I2,      // ELEMENT_TYPE_I2
4931             VT_UI2,     // ELEMENT_TYPE_U2
4932             VT_I4,      // ELEMENT_TYPE_I4
4933             VT_UI4,     // ELEMENT_TYPE_U4
4934             VT_I8,      // ELEMENT_TYPE_I8
4935             VT_UI8,     // ELEMENT_TYPE_U8
4936             VT_R4,      // ELEMENT_TYPE_R4
4937             VT_R8       // ELEMENT_TYPE_R8
4938
4939         };
4940
4941         _ASSERTE(map[etElement] != VT_NULL);        
4942         m_vtElement = map[etElement];
4943     }
4944     else
4945     {
4946         if (m_thElement == TypeHandle(g_pStringClass))
4947         {           
4948             switch (ntElement)
4949             {
4950                 case NATIVE_TYPE_DEFAULT:
4951 #ifdef FEATURE_COMINTEROP
4952                     if (arrayNativeType == NATIVE_TYPE_SAFEARRAY || ms == MarshalInfo::MARSHAL_SCENARIO_COMINTEROP)
4953                     {
4954                         m_vtElement = VT_BSTR;
4955                     }
4956                     else
4957 #endif // FEATURE_COMINTEROP
4958                     {
4959                         m_vtElement = static_cast<VARTYPE>(isAnsi ? VT_LPSTR : VT_LPWSTR);
4960                     }
4961                     break;
4962                 case NATIVE_TYPE_BSTR:
4963                     m_vtElement = VT_BSTR;
4964                     break;
4965                 case NATIVE_TYPE_LPSTR:
4966                     m_vtElement = VT_LPSTR;
4967                     break;
4968                 case NATIVE_TYPE_LPWSTR:
4969                     m_vtElement = VT_LPWSTR;
4970                     break;
4971                 case NATIVE_TYPE_LPTSTR:
4972                 {
4973 #ifdef FEATURE_COMINTEROP
4974                     if (ms == MarshalInfo::MARSHAL_SCENARIO_COMINTEROP || IsAMIExport(m_flags))
4975                     {
4976                         // We disallow NATIVE_TYPE_LPTSTR for COM or if we are exporting. 
4977                         ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHALPARAM_NO_LPTSTR);
4978                     }
4979                     else
4980 #endif // FEATURE_COMINTEROP
4981                     {
4982                         // We no longer support Win9x so LPTSTR always maps to a Unicode string.
4983                         m_vtElement = VT_LPWSTR;
4984                     }
4985                     break;
4986                 }
4987
4988                 default:
4989                     ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_STRINGARRAY);
4990             }
4991         }
4992         else if (m_thElement == TypeHandle(g_pObjectClass))
4993         {
4994 #ifdef FEATURE_COMINTEROP
4995             switch(ntElement)
4996             {
4997                 case NATIVE_TYPE_DEFAULT:
4998                     if (ms == MarshalInfo::MARSHAL_SCENARIO_FIELD)
4999                         m_vtElement = VT_UNKNOWN;
5000                     else
5001                         m_vtElement = VT_VARIANT;
5002                     break;
5003                     
5004                 case NATIVE_TYPE_STRUCT:
5005                     m_vtElement = VT_VARIANT;
5006                     break;
5007
5008                 case NATIVE_TYPE_INTF:
5009                 case NATIVE_TYPE_IUNKNOWN:
5010                     m_vtElement = VT_UNKNOWN;
5011                     break;
5012
5013                 case NATIVE_TYPE_IDISPATCH:
5014                     m_vtElement = VT_DISPATCH;
5015                     break;
5016
5017                 default:
5018                     ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_OBJECTARRAY);
5019             }
5020
5021 #else // FEATURE_COMINTEROP
5022             switch (ntElement)
5023             {
5024                 case NATIVE_TYPE_IUNKNOWN:
5025                     m_vtElement = VT_UNKNOWN;
5026                     break;
5027
5028                 default:
5029                     ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_UNSUPPORTED_SIG);
5030             }
5031 #endif // FEATURE_COMINTEROP
5032         }
5033         else if (m_thElement.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__SAFE_HANDLE))))
5034         {
5035             // Array's of SAFEHANDLEs are not supported.
5036             ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_SAFEHANDLEARRAY);
5037         }
5038         else if (m_thElement.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__CRITICAL_HANDLE))))
5039         {
5040             // Array's of CRITICALHANDLEs are not supported.
5041             ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_CRITICALHANDLEARRAY);
5042         }
5043         else if (etElement == ELEMENT_TYPE_VALUETYPE) 
5044         {
5045             if (m_thElement == TypeHandle(MscorlibBinder::GetClass(CLASS__DATE_TIME)))
5046             {
5047                 if (ntElement == NATIVE_TYPE_STRUCT || ntElement == NATIVE_TYPE_DEFAULT)
5048                     m_vtElement = VT_DATE;
5049                 else
5050                     ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_DATETIMEARRAY);
5051             }
5052             else if (m_thElement == TypeHandle(MscorlibBinder::GetClass(CLASS__DECIMAL)))
5053             {
5054                 if (ntElement == NATIVE_TYPE_STRUCT || ntElement == NATIVE_TYPE_DEFAULT)
5055                     m_vtElement = VT_DECIMAL;
5056 #ifdef FEATURE_COMINTEROP               
5057                 else if (ntElement == NATIVE_TYPE_CURRENCY)
5058                     m_vtElement = VT_CY;
5059 #endif // FEATURE_COMINTEROP
5060                 else
5061                     ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_DECIMALARRAY);                
5062             }
5063             else
5064             {
5065                 // When exporting, we need to handle enums specially.
5066                 if (IsAMIExport(m_flags) && m_thElement.IsEnum())
5067                 {
5068                     // Get the element type of the underlying type.
5069                     CorElementType et = m_thElement.GetInternalCorElementType();
5070                     
5071                     // If it is not a 32-bit type, convert as the underlying type.
5072                     if ((et == ELEMENT_TYPE_I4) || (et == ELEMENT_TYPE_U4))
5073                         m_vtElement = VT_RECORD;             
5074                     else
5075                         m_vtElement = OleVariant::GetVarTypeForTypeHandle(m_thElement);
5076                 }             
5077                 else
5078                 {                   
5079                     m_vtElement = OleVariant::GetVarTypeForTypeHandle(m_thElement);
5080                 }
5081             }
5082         }
5083 #ifdef FEATURE_COMINTEROP
5084         else if (m_thElement == TypeHandle(MscorlibBinder::GetClass(CLASS__ERROR_WRAPPER)))
5085         {
5086             m_vtElement = VT_ERROR;
5087         }
5088 #endif
5089         else
5090         {
5091 #ifdef FEATURE_COMINTEROP
5092
5093             // Compat: Even if the classes have layout, we still convert them to interface pointers.
5094
5095             ItfMarshalInfo itfInfo;
5096             MarshalInfo::GetItfMarshalInfo(m_thElement, TypeHandle(), FALSE, FALSE, ms, &itfInfo);
5097
5098             // Compat: We must always do VT_UNKNOWN marshaling for parameters, even if the interface is marked late-bound.
5099             if (ms == MarshalInfo::MARSHAL_SCENARIO_FIELD)
5100                 m_vtElement = static_cast<VARTYPE>(!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF) ? VT_DISPATCH : VT_UNKNOWN);
5101             else
5102                 m_vtElement = VT_UNKNOWN;
5103             
5104             m_thElement = itfInfo.thItf.IsNull() ? TypeHandle(g_pObjectClass) : itfInfo.thItf;
5105             m_thInterfaceArrayElementClass = itfInfo.thClass;
5106             
5107 #else // FEATURE_COMINTEROP
5108             ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_UNSUPPORTED_SIG);
5109 #endif // FEATURE_COMINTEROP
5110         }
5111     }
5112
5113    // Avoid throwing exceptions for any managed structs that have layouts and have types of fields that gets default to those banned types by default 
5114    // 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
5115    if (AppX::IsAppXProcess() && ms != MarshalInfo::MARSHAL_SCENARIO_FIELD)
5116     {
5117        bool set_error = false;
5118        UINT m_resID = 0;  
5119        switch (m_vtElement)
5120        {
5121            case VT_DISPATCH:
5122                  m_resID = IDS_EE_BADMARSHAL_TYPE_IDISPATCH ;
5123                  set_error = true;
5124                 break;
5125        }
5126         if (set_error)
5127             COMPlusThrow(kPlatformNotSupportedException, m_resID);
5128     }
5129
5130     // If we are exporting, we need to substitute the VTHACK_* VARTYPE with the actual
5131     // types as expressed in the type library.
5132     if (IsAMIExport(m_flags))
5133     {
5134         if (m_vtElement == VTHACK_ANSICHAR)
5135             m_vtElement = VT_UI1;
5136         else if (m_vtElement == VTHACK_WINBOOL)
5137             m_vtElement = VT_I4;
5138                 else if (m_vtElement == VTHACK_CBOOL)
5139                     m_vtElement = VT_UI1;
5140     }
5141
5142 LExit:;
5143     
5144     RETURN;
5145 }
5146
5147 bool IsUnsupportedValueTypeReturn(MetaSig& msig)
5148 {
5149     CONTRACTL
5150     {
5151         THROWS;
5152         GC_TRIGGERS;
5153         MODE_ANY;
5154     }
5155     CONTRACTL_END
5156     
5157     CorElementType type = msig.GetReturnTypeNormalized();
5158     
5159     if (type == ELEMENT_TYPE_VALUETYPE || type == ELEMENT_TYPE_TYPEDBYREF)
5160     {
5161 #ifdef _TARGET_X86_
5162         // On x86, the internal CorElementType for value types is normalized by the type loader
5163         // (see calls to ComputeInternalCorElementTypeForValueType in MethodTableBuilder).
5164         // We don't need to redo the normalization here.
5165         return true;
5166 #else
5167         TypeHandle th = msig.GetRetTypeHandleThrowing();
5168         
5169         return EEClass::ComputeInternalCorElementTypeForValueType(th.GetMethodTable()) == ELEMENT_TYPE_VALUETYPE;
5170 #endif // _TARGET_X86_
5171     }
5172
5173     return false;
5174 }
5175
5176 #ifndef CROSSGEN_COMPILE
5177
5178 #include "stubhelpers.h"
5179 FCIMPL3(void*, StubHelpers::CreateCustomMarshalerHelper, 
5180             MethodDesc* pMD,
5181             mdToken paramToken,
5182             TypeHandle hndManagedType)
5183 {
5184     FCALL_CONTRACT;
5185
5186     CustomMarshalerHelper* pCMHelper = NULL;
5187
5188     HELPER_METHOD_FRAME_BEGIN_RET_0();
5189     
5190     Module* pModule = pMD->GetModule();
5191     Assembly* pAssembly = pModule->GetAssembly();
5192     
5193
5194 #ifdef FEATURE_COMINTEROP
5195     if (!hndManagedType.IsTypeDesc() &&
5196         IsTypeRefOrDef(g_CollectionsEnumeratorClassName, hndManagedType.GetModule(), hndManagedType.GetCl()))
5197     {
5198         pCMHelper = SetupCustomMarshalerHelper(ENUMERATOR_TO_ENUM_VARIANT_CM_NAME, 
5199                                                ENUMERATOR_TO_ENUM_VARIANT_CM_NAME_LEN,
5200                                                ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE, 
5201                                                ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE_LEN, 
5202                                                pAssembly, hndManagedType);
5203     }
5204     else
5205 #endif // FEATURE_COMINTEROP
5206     {
5207         //
5208         // Retrieve the native type for the current parameter.
5209         //
5210
5211         BOOL result;
5212         NativeTypeParamInfo ParamInfo;
5213         result = ParseNativeTypeInfo(paramToken, pModule->GetMDImport(), &ParamInfo);
5214
5215         //
5216         // this should all have been done at stub creation time
5217         //
5218         CONSISTENCY_CHECK(result != 0);
5219         CONSISTENCY_CHECK(ParamInfo.m_NativeType == NATIVE_TYPE_CUSTOMMARSHALER);
5220         
5221         // Set up the custom marshaler info.
5222         pCMHelper = SetupCustomMarshalerHelper(ParamInfo.m_strCMMarshalerTypeName, 
5223                                                 ParamInfo.m_cCMMarshalerTypeNameBytes,
5224                                                 ParamInfo.m_strCMCookie, 
5225                                                 ParamInfo.m_cCMCookieStrBytes,
5226                                                 pAssembly,
5227                                                 hndManagedType);
5228     }
5229
5230     HELPER_METHOD_FRAME_END();
5231
5232     return (void*)pCMHelper;
5233 }
5234 FCIMPLEND
5235
5236 #endif // CROSSGEN_COMPILE