Remove Marshaling MDA (#22579)
[platform/upstream/coreclr.git] / src / vm / fieldmarshaler.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: FieldMarshaler.cpp
6 //
7
8 //
9
10
11 #include "common.h"
12 #include "vars.hpp"
13 #include "class.h"
14 #include "ceeload.h"
15 #include "excep.h"
16 #include "fieldmarshaler.h"
17 #include "field.h"
18 #include "frames.h"
19 #include "dllimport.h"
20 #include "comdelegate.h"
21 #include "eeconfig.h"
22 #include "comdatetime.h"
23 #include "olevariant.h"
24 #include <cor.h>
25 #include <corpriv.h>
26 #include <corerror.h>
27 #include "sigformat.h"
28 #include "marshalnative.h"
29 #include "typeparse.h"
30 #ifdef FEATURE_COMINTEROP
31 #include <winstring.h>
32 #endif // FEATURE_COMINTEROP
33
34 // forward declaration
35 BOOL CheckForPrimitiveType(CorElementType elemType, CQuickArray<WCHAR> *pStrPrimitiveType);
36 TypeHandle ArraySubTypeLoadWorker(const SString &strUserDefTypeName, Assembly* pAssembly);
37 TypeHandle GetFieldTypeHandleWorker(MetaSig *pFieldSig);
38 #ifdef _DEBUG
39 BOOL IsFixedBuffer(mdFieldDef field, IMDInternalImport *pInternalImport);
40 #endif
41
42
43 //=======================================================================
44 // A database of NFT types.
45 //=======================================================================
46 struct NFTDataBaseEntry
47 {
48     UINT32            m_cbNativeSize;     // native size of field (0 if not constant)
49     bool              m_fWinRTSupported;  // true if the field marshaler is supported for WinRT
50 };
51
52 static const NFTDataBaseEntry NFTDataBase[] =
53 {
54     #undef DEFINE_NFT
55     #define DEFINE_NFT(name, nativesize, fWinRTSupported) { nativesize, fWinRTSupported },
56     #include "nsenums.h"
57 };
58
59
60 //=======================================================================
61 // This is invoked from the class loader while building the internal structures for a type
62 // This function should check if explicit layout metadata exists.
63 //
64 // Returns:
65 //  TRUE    - yes, there's layout metadata
66 //  FALSE   - no, there's no layout.
67 //  fail    - throws a typeload exception
68 //
69 // If TRUE,
70 //   *pNLType            gets set to nltAnsi or nltUnicode
71 //   *pPackingSize       declared packing size
72 //   *pfExplicitoffsets  offsets explicit in metadata or computed?
73 //=======================================================================
74 BOOL HasLayoutMetadata(Assembly* pAssembly, IMDInternalImport *pInternalImport, mdTypeDef cl, MethodTable*pParentMT, BYTE *pPackingSize, BYTE *pNLTType, BOOL *pfExplicitOffsets)
75 {
76     CONTRACTL
77     {
78         THROWS;
79         GC_TRIGGERS;
80         MODE_ANY;
81         PRECONDITION(CheckPointer(pInternalImport));
82         PRECONDITION(CheckPointer(pPackingSize));
83         PRECONDITION(CheckPointer(pNLTType));
84         PRECONDITION(CheckPointer(pfExplicitOffsets));
85     }
86     CONTRACTL_END;
87     
88     HRESULT hr;
89     ULONG clFlags;
90 #ifdef _DEBUG
91     clFlags = 0xcccccccc;
92 #endif
93     
94     if (FAILED(pInternalImport->GetTypeDefProps(cl, &clFlags, NULL)))
95     {
96         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
97     }
98     
99     if (IsTdAutoLayout(clFlags))
100     {
101         // <BUGNUM>workaround for B#104780 - VC fails to set SequentialLayout on some classes
102         // with ClassSize. Too late to fix compiler for V1.
103         //
104         // To compensate, we treat AutoLayout classes as Sequential if they
105         // meet all of the following criteria:
106         //
107         //    - ClassSize present and nonzero.
108         //    - No instance fields declared
109         //    - Base class is System.ValueType.
110         //</BUGNUM>
111         ULONG cbTotalSize = 0;
112         if (SUCCEEDED(pInternalImport->GetClassTotalSize(cl, &cbTotalSize)) && cbTotalSize != 0)
113         {
114             if (pParentMT && pParentMT->IsValueTypeClass())
115             {
116                 MDEnumHolder hEnumField(pInternalImport);
117                 if (SUCCEEDED(pInternalImport->EnumInit(mdtFieldDef, cl, &hEnumField)))
118                 {
119                     ULONG numFields = pInternalImport->EnumGetCount(&hEnumField);
120                     if (numFields == 0)
121                     {
122                         *pfExplicitOffsets = FALSE;
123                         *pNLTType = nltAnsi;
124                         *pPackingSize = 1;
125                         return TRUE;
126                     }
127                 }
128             }
129         }
130         
131         return FALSE;
132     }
133     else if (IsTdSequentialLayout(clFlags))
134     {
135         *pfExplicitOffsets = FALSE;
136     }
137     else if (IsTdExplicitLayout(clFlags))
138     {
139         *pfExplicitOffsets = TRUE;
140     }
141     else
142     {
143         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
144     }
145     
146     // We now know this class has seq. or explicit layout. Ensure the parent does too.
147     if (pParentMT && !(pParentMT->IsObjectClass() || pParentMT->IsValueTypeClass()) && !(pParentMT->HasLayout()))
148         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
149
150     if (IsTdAnsiClass(clFlags))
151     {
152         *pNLTType = nltAnsi;
153     }
154     else if (IsTdUnicodeClass(clFlags))
155     {
156         *pNLTType = nltUnicode;
157     }
158     else if (IsTdAutoClass(clFlags))
159     {
160         // We no longer support Win9x so TdAuto always maps to Unicode.
161         *pNLTType = nltUnicode;
162     }
163     else
164     {
165         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
166     }
167
168     DWORD dwPackSize;
169     hr = pInternalImport->GetClassPackSize(cl, &dwPackSize);
170     if (FAILED(hr) || dwPackSize == 0) 
171         dwPackSize = DEFAULT_PACKING_SIZE;
172
173     // This has to be reduced to a BYTE value, so we had better make sure it fits. If
174     // not, we'll throw an exception instead of trying to munge the value to what we
175     // think the user might want.
176     if (!FitsInU1((UINT64)(dwPackSize)))
177     {
178         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
179     }
180
181     *pPackingSize = (BYTE)dwPackSize;
182     
183     return TRUE;
184 }
185
186 typedef enum
187 {
188     ParseNativeTypeFlag_None    = 0x00,
189     ParseNativeTypeFlag_IsAnsi  = 0x01,
190
191 #ifdef FEATURE_COMINTEROP
192     ParseNativeTypeFlag_IsWinRT = 0x02,
193 #endif // FEATURE_COMINTEROP
194 }
195 ParseNativeTypeFlags;
196
197 inline ParseNativeTypeFlags operator|=(ParseNativeTypeFlags& lhs, ParseNativeTypeFlags rhs)
198 {
199     LIMITED_METHOD_CONTRACT;
200     lhs = static_cast<ParseNativeTypeFlags>(lhs | rhs);
201     return lhs;
202 }
203
204 #ifdef _PREFAST_
205 #pragma warning(push)
206 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
207 #endif
208 VOID ParseNativeType(Module*                     pModule,
209                          PCCOR_SIGNATURE             pCOMSignature,
210                          DWORD                       cbCOMSignature,
211                          ParseNativeTypeFlags        flags,
212                          LayoutRawFieldInfo*         pfwalk,
213                          PCCOR_SIGNATURE             pNativeType,
214                          ULONG                       cbNativeType,
215                          IMDInternalImport*          pInternalImport,
216                          mdTypeDef                   cl,
217                          const SigTypeContext *      pTypeContext,
218                          BOOL                       *pfDisqualifyFromManagedSequential  // set to TRUE if needed (never set to FALSE, it may come in as TRUE!)
219 #ifdef _DEBUG
220                          ,
221                          LPCUTF8                     szNamespace,
222                          LPCUTF8                     szClassName,
223                          LPCUTF8                     szFieldName
224 #endif
225                         )
226 {
227     CONTRACTL
228     {
229         STANDARD_VM_CHECK;
230         PRECONDITION(CheckPointer(pfwalk));
231     }
232     CONTRACTL_END;
233
234     // Make sure that there is no junk in the unused part of the field marshaler space (ngen image determinism)
235     ZeroMemory(&pfwalk->m_FieldMarshaler, MAXFIELDMARSHALERSIZE);
236
237 #define INITFIELDMARSHALER(nfttype, fmtype, args)       \
238 do                                                      \
239 {                                                       \
240     static_assert_no_msg(sizeof(fmtype) <= MAXFIELDMARSHALERSIZE);  \
241     pfwalk->m_nft = (nfttype);                          \
242     new ( &(pfwalk->m_FieldMarshaler) ) fmtype args;    \
243     ((FieldMarshaler*)&(pfwalk->m_FieldMarshaler))->SetNStructFieldType(nfttype); \
244 } while(0)
245
246     BOOL                fAnsi               = (flags & ParseNativeTypeFlag_IsAnsi);
247 #ifdef FEATURE_COMINTEROP
248     BOOL                fIsWinRT            = (flags & ParseNativeTypeFlag_IsWinRT);
249 #endif // FEATURE_COMINTEROP
250     CorElementType      corElemType         = ELEMENT_TYPE_END;
251     PCCOR_SIGNATURE     pNativeTypeStart    = pNativeType;    
252     ULONG               cbNativeTypeStart   = cbNativeType;
253     CorNativeType       ntype;
254     BOOL                fDefault;
255     BOOL                BestFit;
256     BOOL                ThrowOnUnmappableChar;
257     
258     pfwalk->m_nft = NFT_NONE;
259
260     if (cbNativeType == 0)
261     {
262         ntype = NATIVE_TYPE_DEFAULT;
263         fDefault = TRUE;
264     }
265     else
266     {
267         ntype = (CorNativeType) *( ((BYTE*&)pNativeType)++ );
268         cbNativeType--;
269         fDefault = (ntype == NATIVE_TYPE_DEFAULT);
270     }
271
272 #ifdef FEATURE_COMINTEROP
273     if (fIsWinRT && !fDefault)
274     {
275         // Do not allow any MarshalAs in WinRT scenarios - marshaling is fully described by the field type.
276         INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_WINRT_MARSHAL_AS));
277     }
278 #endif // FEATURE_COMINTEROP
279
280     // Setup the signature and normalize
281     MetaSig fsig(pCOMSignature, cbCOMSignature, pModule, pTypeContext, MetaSig::sigField);
282     corElemType = fsig.NextArgNormalized();
283
284
285     if (!(*pfDisqualifyFromManagedSequential))
286     {
287         // This type may qualify for ManagedSequential. Collect managed size and alignment info.
288         if (CorTypeInfo::IsPrimitiveType(corElemType))
289         {
290             pfwalk->m_managedSize = ((UINT32)CorTypeInfo::Size(corElemType)); // Safe cast - no primitive type is larger than 4gb!
291 #if defined(_TARGET_X86_) && defined(UNIX_X86_ABI)
292             switch (corElemType)
293             {
294                 // The System V ABI for i386 defines different packing for these types.
295                 case ELEMENT_TYPE_I8:
296                 case ELEMENT_TYPE_U8:
297                 case ELEMENT_TYPE_R8:
298                 {
299                     pfwalk->m_managedAlignmentReq = 4;
300                     break;
301                 }
302
303                 default:
304                 {
305                     pfwalk->m_managedAlignmentReq = pfwalk->m_managedSize;
306                     break;
307                 }
308             }
309 #else // _TARGET_X86_ && UNIX_X86_ABI
310             pfwalk->m_managedAlignmentReq = pfwalk->m_managedSize;
311 #endif
312         }
313         else if (corElemType == ELEMENT_TYPE_PTR)
314         {
315             pfwalk->m_managedSize = TARGET_POINTER_SIZE;
316             pfwalk->m_managedAlignmentReq = TARGET_POINTER_SIZE;
317         }
318         else if (corElemType == ELEMENT_TYPE_VALUETYPE)
319         {
320             TypeHandle pNestedType = fsig.GetLastTypeHandleThrowing(ClassLoader::LoadTypes,
321                                                                     CLASS_LOAD_APPROXPARENTS,
322                                                                     TRUE);
323             if (pNestedType.GetMethodTable()->IsManagedSequential())
324             {
325                 pfwalk->m_managedSize = (pNestedType.GetMethodTable()->GetNumInstanceFieldBytes());
326
327                 _ASSERTE(pNestedType.GetMethodTable()->HasLayout()); // If it is ManagedSequential(), it also has Layout but doesn't hurt to check before we do a cast!
328                 pfwalk->m_managedAlignmentReq = pNestedType.GetMethodTable()->GetLayoutInfo()->m_ManagedLargestAlignmentRequirementOfAllMembers;
329             }
330             else
331             {
332                 *pfDisqualifyFromManagedSequential = TRUE;
333             }
334         }
335         else
336         {
337             // No other type permitted for ManagedSequential.
338             *pfDisqualifyFromManagedSequential = TRUE;
339         }
340     }
341
342 #ifdef _TARGET_X86_
343     // Normalization might have put corElementType and ntype out of sync which can
344     // result in problems with non-default ntype being validated against the 
345     // normalized primitive corElemType.
346     //
347     VerifyAndAdjustNormalizedType(pModule, fsig.GetArgProps(), fsig.GetSigTypeContext(), &corElemType, &ntype);
348
349     fDefault = (ntype == NATIVE_TYPE_DEFAULT);
350 #endif // _TARGET_X86_
351
352     CorElementType sigElemType;
353     IfFailThrow(fsig.GetArgProps().PeekElemType(&sigElemType));
354     if ((sigElemType == ELEMENT_TYPE_GENERICINST || sigElemType == ELEMENT_TYPE_VAR) && corElemType == ELEMENT_TYPE_CLASS)
355     {
356         INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_GENERICS_RESTRICTION));
357     }
358     else switch (corElemType)
359     {
360         case ELEMENT_TYPE_CHAR:
361             if (fDefault)
362             {
363                 if (fAnsi)
364                 {
365                     ReadBestFitCustomAttribute(pInternalImport, cl, &BestFit, &ThrowOnUnmappableChar);
366                     INITFIELDMARSHALER(NFT_ANSICHAR, FieldMarshaler_Ansi, (BestFit, ThrowOnUnmappableChar));
367                 }
368                 else
369                 {
370                     INITFIELDMARSHALER(NFT_COPY2, FieldMarshaler_Copy2, ());
371                 }
372             }
373             else if (ntype == NATIVE_TYPE_I1 || ntype == NATIVE_TYPE_U1)
374             {
375                 ReadBestFitCustomAttribute(pInternalImport, cl, &BestFit, &ThrowOnUnmappableChar);
376                 INITFIELDMARSHALER(NFT_ANSICHAR, FieldMarshaler_Ansi, (BestFit, ThrowOnUnmappableChar));
377             }
378             else if (ntype == NATIVE_TYPE_I2 || ntype == NATIVE_TYPE_U2)
379             {
380                 INITFIELDMARSHALER(NFT_COPY2, FieldMarshaler_Copy2, ());
381             }
382             else
383             {
384                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_CHAR));
385             }
386             break;
387
388         case ELEMENT_TYPE_BOOLEAN:
389             if (fDefault)
390             {
391 #ifdef FEATURE_COMINTEROP
392                 if (fIsWinRT)
393                 {
394                     INITFIELDMARSHALER(NFT_CBOOL, FieldMarshaler_CBool, ());
395                 }
396                 else
397 #endif // FEATURE_COMINTEROP
398                 {
399                     INITFIELDMARSHALER(NFT_WINBOOL, FieldMarshaler_WinBool, ());
400                 }
401             }
402             else if (ntype == NATIVE_TYPE_BOOLEAN)
403             {
404                 INITFIELDMARSHALER(NFT_WINBOOL, FieldMarshaler_WinBool, ());
405             }
406 #ifdef FEATURE_COMINTEROP
407             else if (ntype == NATIVE_TYPE_VARIANTBOOL)
408             {
409                 INITFIELDMARSHALER(NFT_VARIANTBOOL, FieldMarshaler_VariantBool, ());
410             }
411 #endif // FEATURE_COMINTEROP
412             else if (ntype == NATIVE_TYPE_U1 || ntype == NATIVE_TYPE_I1)
413             {
414                 INITFIELDMARSHALER(NFT_CBOOL, FieldMarshaler_CBool, ());
415             }
416             else
417             {
418                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_BOOLEAN));
419             }
420             break;
421
422
423         case ELEMENT_TYPE_I1:
424             if (fDefault || ntype == NATIVE_TYPE_I1 || ntype == NATIVE_TYPE_U1)
425             {
426                 INITFIELDMARSHALER(NFT_COPY1, FieldMarshaler_Copy1, ());
427             }
428             else
429             {
430                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_I1));
431             }
432             break;
433
434         case ELEMENT_TYPE_U1:
435             if (fDefault || ntype == NATIVE_TYPE_U1 || ntype == NATIVE_TYPE_I1)
436             {
437                 INITFIELDMARSHALER(NFT_COPY1, FieldMarshaler_Copy1, ());
438             }
439             else
440             {
441                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_I1));
442             }
443             break;
444
445         case ELEMENT_TYPE_I2:
446             if (fDefault || ntype == NATIVE_TYPE_I2 || ntype == NATIVE_TYPE_U2)
447             {
448                 INITFIELDMARSHALER(NFT_COPY2, FieldMarshaler_Copy2, ());
449             }
450             else
451             {
452                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_I2));
453             }
454             break;
455
456         case ELEMENT_TYPE_U2:
457             if (fDefault || ntype == NATIVE_TYPE_U2 || ntype == NATIVE_TYPE_I2)
458             {
459                 INITFIELDMARSHALER(NFT_COPY2, FieldMarshaler_Copy2, ());
460             }
461             else
462             {
463                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_I2));
464             }
465             break;
466
467         case ELEMENT_TYPE_I4:
468             if (fDefault || ntype == NATIVE_TYPE_I4 || ntype == NATIVE_TYPE_U4 || ntype == NATIVE_TYPE_ERROR)
469             {
470                 INITFIELDMARSHALER(NFT_COPY4, FieldMarshaler_Copy4, ());
471             }
472             else
473             {
474                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_I4));
475             }
476             break;
477             
478         case ELEMENT_TYPE_U4:
479             if (fDefault || ntype == NATIVE_TYPE_U4 || ntype == NATIVE_TYPE_I4 || ntype == NATIVE_TYPE_ERROR)
480             {
481                 INITFIELDMARSHALER(NFT_COPY4, FieldMarshaler_Copy4, ());
482             }
483             else
484             {
485                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_I4));
486             }
487             break;
488
489         case ELEMENT_TYPE_I8:
490             if (fDefault || ntype == NATIVE_TYPE_I8 || ntype == NATIVE_TYPE_U8)
491             {
492                 INITFIELDMARSHALER(NFT_COPY8, FieldMarshaler_Copy8, ());
493             }
494             else
495             {
496                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_I8));
497             }
498             break;
499
500         case ELEMENT_TYPE_U8:
501             if (fDefault || ntype == NATIVE_TYPE_U8 || ntype == NATIVE_TYPE_I8)
502             {
503                 INITFIELDMARSHALER(NFT_COPY8, FieldMarshaler_Copy8, ());
504             }
505             else
506             {
507                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_I8));
508             }
509             break;
510
511         case ELEMENT_TYPE_I: //fallthru
512         case ELEMENT_TYPE_U:
513 #ifdef FEATURE_COMINTEROP
514             if (fIsWinRT)
515             {
516                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE));
517             }
518             else
519 #endif // FEATURE_COMINTEROP
520             if (fDefault || ntype == NATIVE_TYPE_INT || ntype == NATIVE_TYPE_UINT)
521             {
522 #ifdef _TARGET_64BIT_
523                 INITFIELDMARSHALER(NFT_COPY8, FieldMarshaler_Copy8, ());
524 #else // !_TARGET_64BIT_
525                 INITFIELDMARSHALER(NFT_COPY4, FieldMarshaler_Copy4, ());
526 #endif // !_TARGET_64BIT_
527             }
528             else
529             {
530                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_I));
531             }
532             break;
533
534         case ELEMENT_TYPE_R4:
535             if (fDefault || ntype == NATIVE_TYPE_R4)
536             {
537                 INITFIELDMARSHALER(NFT_COPY4, FieldMarshaler_Copy4, ());
538             }
539             else
540             {
541                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_R4));
542             }
543             break;
544             
545         case ELEMENT_TYPE_R8:
546             if (fDefault || ntype == NATIVE_TYPE_R8)
547             {
548                 INITFIELDMARSHALER(NFT_COPY8, FieldMarshaler_Copy8, ());
549             }
550             else
551             {
552                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_R8));
553             }
554             break;
555
556         case ELEMENT_TYPE_PTR:
557 #ifdef FEATURE_COMINTEROP
558             if (fIsWinRT)
559             {
560                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE));
561             }
562             else
563 #endif // FEATURE_COMINTEROP
564             if (fDefault)
565             {
566 #ifdef _TARGET_64BIT_
567                 INITFIELDMARSHALER(NFT_COPY8, FieldMarshaler_Copy8, ());
568 #else // !_TARGET_64BIT_
569                 INITFIELDMARSHALER(NFT_COPY4, FieldMarshaler_Copy4, ());
570 #endif // !_TARGET_64BIT_
571             }
572             else
573             {
574                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_PTR));
575             }
576             break;
577
578         case ELEMENT_TYPE_VALUETYPE:
579         {
580             // This may cause a TypeLoadException, which we currently seem to have to swallow.
581             // This happens with structs that contain fields of class type where the class itself
582             // refers to the struct in a field.
583             TypeHandle thNestedType = GetFieldTypeHandleWorker(&fsig);
584             if (!thNestedType.GetMethodTable())
585                 break;
586 #ifdef FEATURE_COMINTEROP
587             if (fIsWinRT && sigElemType == ELEMENT_TYPE_GENERICINST)
588             {
589                 // If this is a generic value type, lets see whether it is a Nullable<T>
590                 TypeHandle genType = fsig.GetLastTypeHandleThrowing();
591                 if(genType != NULL && genType.GetMethodTable()->HasSameTypeDefAs(g_pNullableClass))
592                 {
593                     // The generic type is System.Nullable<T>. 
594                     // Lets extract the typeArg and check if the typeArg is valid.
595                     // typeArg is invalid if
596                     // 1. It is not a value type.
597                     // 2. It is string
598                     // 3. We have an open type with us.
599                     Instantiation inst = genType.GetMethodTable()->GetInstantiation();
600                     MethodTable* typeArgMT = inst[0].GetMethodTable();
601                     if (!typeArgMT->IsLegalNonArrayWinRTType())
602                     {
603                         // Type is not a valid WinRT value type.
604                         INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_NULLABLE_RESTRICTION));
605                     }
606                     else
607                     {
608                         INITFIELDMARSHALER(NFT_WINDOWSFOUNDATIONIREFERENCE, FieldMarshaler_Nullable, (genType.GetMethodTable()));
609                     }
610                     break;
611                 }
612             }
613 #endif
614            if (fsig.IsClass(g_DateClassName))
615             {
616                 if (fDefault || ntype == NATIVE_TYPE_STRUCT)
617                 {
618                     INITFIELDMARSHALER(NFT_DATE, FieldMarshaler_Date, ());
619                 }
620                 else
621                 {
622                     INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_DATETIME));
623                 }
624             }
625             else if (fsig.IsClass(g_DecimalClassName))
626             {
627                 if (fDefault || ntype == NATIVE_TYPE_STRUCT)
628                 {
629                     INITFIELDMARSHALER(NFT_DECIMAL, FieldMarshaler_Decimal, ());
630                 }
631 #ifdef FEATURE_COMINTEROP
632                 else if (ntype == NATIVE_TYPE_CURRENCY)
633                 {
634                     INITFIELDMARSHALER(NFT_CURRENCY, FieldMarshaler_Currency, ());
635                 }
636 #endif // FEATURE_COMINTEROP
637                 else
638                 {
639                     INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHALFIELD_DECIMAL));                    
640                 }
641             }
642 #ifdef FEATURE_COMINTEROP
643             else if (fsig.IsClass(g_DateTimeOffsetClassName))
644             {
645                 if (fDefault || ntype == NATIVE_TYPE_STRUCT)
646                 {
647                     INITFIELDMARSHALER(NFT_DATETIMEOFFSET, FieldMarshaler_DateTimeOffset, ());
648                 }
649                 else
650                 {
651                     INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_DATETIMEOFFSET));
652                 }
653             }
654             else if (fIsWinRT && !thNestedType.GetMethodTable()->IsLegalNonArrayWinRTType())
655             {
656                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE));
657             }
658 #endif // FEATURE_COMINTEROP
659             else if (thNestedType.GetMethodTable()->HasLayout())
660             {
661                 if (fDefault || ntype == NATIVE_TYPE_STRUCT)
662                 {
663                     if (IsStructMarshalable(thNestedType))
664                     {
665 #ifdef _DEBUG
666                         INITFIELDMARSHALER(NFT_NESTEDVALUECLASS, FieldMarshaler_NestedValueClass, (thNestedType.GetMethodTable(), IsFixedBuffer(pfwalk->m_MD, pInternalImport)));
667 #else
668                         INITFIELDMARSHALER(NFT_NESTEDVALUECLASS, FieldMarshaler_NestedValueClass, (thNestedType.GetMethodTable()));
669 #endif
670                     }
671                     else
672                     {
673                         INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_NOTMARSHALABLE));
674                     }
675                 }
676                 else
677                 {
678                     INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_VALUETYPE));                                        
679                 }
680             }
681             else
682             {
683                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_NOTMARSHALABLE));
684             }
685             break;
686         }
687
688         case ELEMENT_TYPE_CLASS:
689         {
690             // This may cause a TypeLoadException, which we currently seem to have to swallow.
691             // This happens with structs that contain fields of class type where the class itself
692             // refers to the struct in a field.
693             TypeHandle thNestedType = GetFieldTypeHandleWorker(&fsig);
694             if (!thNestedType.GetMethodTable())
695                 break;
696                        
697             if (thNestedType.GetMethodTable()->IsObjectClass())
698             {
699 #ifdef FEATURE_COMINTEROP                
700                 if (fDefault || ntype == NATIVE_TYPE_IUNKNOWN || ntype == NATIVE_TYPE_IDISPATCH || ntype == NATIVE_TYPE_INTF)
701                 {
702                     // Only NATIVE_TYPE_IDISPATCH maps to an IDispatch based interface pointer.
703                     DWORD dwFlags = ItfMarshalInfo::ITF_MARSHAL_USE_BASIC_ITF;
704                     if (ntype == NATIVE_TYPE_IDISPATCH)
705                     {
706                         dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
707                     }
708                     INITFIELDMARSHALER(NFT_INTERFACE, FieldMarshaler_Interface, (NULL, NULL, dwFlags));
709                 }
710                 else if (ntype == NATIVE_TYPE_STRUCT)
711                 {
712                     INITFIELDMARSHALER(NFT_VARIANT, FieldMarshaler_Variant, ());
713                 }
714 #else // FEATURE_COMINTEROP
715                 if (fDefault || ntype == NATIVE_TYPE_IUNKNOWN || ntype == NATIVE_TYPE_IDISPATCH || ntype == NATIVE_TYPE_INTF)
716                 {
717                     INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_OBJECT_TO_ITF_NOT_SUPPORTED));
718                 }
719                 else if (ntype == NATIVE_TYPE_STRUCT)
720                 {
721                     INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_OBJECT_TO_VARIANT_NOT_SUPPORTED));
722                 }
723 #endif // FEATURE_COMINTEROP
724                 else
725                 {
726                     INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHALFIELD_OBJECT));
727                 }
728             }
729 #ifdef FEATURE_COMINTEROP                
730             else if (ntype == NATIVE_TYPE_INTF || thNestedType.IsInterface())
731             {
732                 if (fIsWinRT && !thNestedType.GetMethodTable()->IsLegalNonArrayWinRTType())
733                 {
734                     INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE));
735                 }
736                 else
737                 {
738                     ItfMarshalInfo itfInfo;
739                     if (FAILED(MarshalInfo::TryGetItfMarshalInfo(thNestedType, FALSE, FALSE, &itfInfo)))
740                         break;
741
742                     INITFIELDMARSHALER(NFT_INTERFACE, FieldMarshaler_Interface, (itfInfo.thClass.GetMethodTable(), itfInfo.thItf.GetMethodTable(), itfInfo.dwFlags));
743                 }
744             }
745 #else  // FEATURE_COMINTEROP
746             else if (ntype == NATIVE_TYPE_INTF || thNestedType.IsInterface())
747             {
748                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_OBJECT_TO_ITF_NOT_SUPPORTED));
749             }
750 #endif // FEATURE_COMINTEROP
751             else if (ntype == NATIVE_TYPE_CUSTOMMARSHALER)
752             {
753                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHALFIELD_NOCUSTOMMARSH));
754             }
755             else if (thNestedType == TypeHandle(g_pStringClass))
756             {
757                 if (fDefault)
758                 {
759 #ifdef FEATURE_COMINTEROP
760                     if (fIsWinRT)
761                     {
762                         INITFIELDMARSHALER(NFT_HSTRING, FieldMarshaler_HSTRING, ());
763                     }
764                     else
765 #endif // FEATURE_COMINTEROP
766                     if (fAnsi)
767                     {
768                         ReadBestFitCustomAttribute(pInternalImport, cl, &BestFit, &ThrowOnUnmappableChar);
769                         INITFIELDMARSHALER(NFT_STRINGANSI, FieldMarshaler_StringAnsi, (BestFit, ThrowOnUnmappableChar));
770                     }
771                     else
772                     {
773                         INITFIELDMARSHALER(NFT_STRINGUNI, FieldMarshaler_StringUni, ());
774                     }
775                 }
776                 else
777                 {
778                     switch (ntype)
779                     {
780                         case NATIVE_TYPE_LPSTR:
781                             ReadBestFitCustomAttribute(pInternalImport, cl, &BestFit, &ThrowOnUnmappableChar);
782                             INITFIELDMARSHALER(NFT_STRINGANSI, FieldMarshaler_StringAnsi, (BestFit, ThrowOnUnmappableChar));
783                             break;
784
785                         case NATIVE_TYPE_LPWSTR:
786                             INITFIELDMARSHALER(NFT_STRINGUNI, FieldMarshaler_StringUni, ());
787                             break;
788                         
789                         case NATIVE_TYPE_LPUTF8STR:
790                                                         INITFIELDMARSHALER(NFT_STRINGUTF8, FieldMarshaler_StringUtf8, ());
791                                                         break;
792
793                         case NATIVE_TYPE_LPTSTR:
794                             // We no longer support Win9x so LPTSTR always maps to a Unicode string.
795                             INITFIELDMARSHALER(NFT_STRINGUNI, FieldMarshaler_StringUni, ());
796                             break;
797
798                         case NATIVE_TYPE_BSTR:
799                             INITFIELDMARSHALER(NFT_BSTR, FieldMarshaler_BSTR, ());
800                             break;
801
802 #ifdef FEATURE_COMINTEROP
803                         case NATIVE_TYPE_HSTRING:
804                             INITFIELDMARSHALER(NFT_HSTRING, FieldMarshaler_HSTRING, ());
805                             break;
806 #endif // FEATURE_COMINTEROP
807                         case NATIVE_TYPE_FIXEDSYSSTRING:
808                             {
809                                 ULONG nchars;
810                                 ULONG udatasize = CorSigUncompressedDataSize(pNativeType);
811
812                                 if (cbNativeType < udatasize)
813                                     break;
814
815                                 nchars = CorSigUncompressData(pNativeType);
816                                 cbNativeType -= udatasize;
817
818                                 if (nchars == 0)
819                                 {
820                                     INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHALFIELD_ZEROLENGTHFIXEDSTRING));
821                                     break;  
822                                 }
823
824                                 if (fAnsi)
825                                 {
826                                     ReadBestFitCustomAttribute(pInternalImport, cl, &BestFit, &ThrowOnUnmappableChar);
827                                     INITFIELDMARSHALER(NFT_FIXEDSTRINGANSI, FieldMarshaler_FixedStringAnsi, (nchars, BestFit, ThrowOnUnmappableChar));
828                                 }
829                                 else
830                                 {
831                                     INITFIELDMARSHALER(NFT_FIXEDSTRINGUNI, FieldMarshaler_FixedStringUni, (nchars));
832                                 }
833                             }
834                         break;
835
836                         default:
837                             INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHALFIELD_STRING));
838                             break;
839                     }
840                 }
841             }
842 #ifdef FEATURE_COMINTEROP
843             else if (fIsWinRT && fsig.IsClass(g_TypeClassName))
844             {   // Note: If the System.Type field is in non-WinRT struct, do not change the previously shipped behavior
845                 INITFIELDMARSHALER(NFT_SYSTEMTYPE, FieldMarshaler_SystemType, ());
846             }
847             else if (fIsWinRT && fsig.IsClass(g_ExceptionClassName))  // Marshal Windows.Foundation.HResult as System.Exception for WinRT.
848             {
849                 INITFIELDMARSHALER(NFT_WINDOWSFOUNDATIONHRESULT, FieldMarshaler_Exception, ());
850             }
851 #endif //FEATURE_COMINTEROP
852 #ifdef FEATURE_CLASSIC_COMINTEROP
853             else if (thNestedType.GetMethodTable() == g_pArrayClass)
854             {
855                 if (ntype == NATIVE_TYPE_SAFEARRAY)
856                 {
857                     NativeTypeParamInfo ParamInfo;
858                     CorElementType etyp = ELEMENT_TYPE_OBJECT;
859                     MethodTable* pMT = NULL;
860                     VARTYPE vtElement = VT_EMPTY;
861
862                     // Compat: If no safe array used def subtype was specified, we assume TypeOf(Object).                            
863                     TypeHandle thElement = TypeHandle(g_pObjectClass);
864
865                     // If we have no native type data, assume default behavior
866                     if (S_OK != CheckForCompressedData(pNativeTypeStart, pNativeType, cbNativeTypeStart))
867                     {
868                         INITFIELDMARSHALER(NFT_SAFEARRAY, FieldMarshaler_SafeArray, (VT_EMPTY, NULL));
869                         break;
870                     }
871       
872                     vtElement = (VARTYPE) (CorSigUncompressData(/*modifies*/pNativeType));
873
874                     // Extract the name of the record type's.
875                     if (S_OK == CheckForCompressedData(pNativeTypeStart, pNativeType, cbNativeTypeStart))
876                     {
877                         ULONG strLen;
878                         if (FAILED(CPackedLen::SafeGetData(pNativeType, pNativeTypeStart + cbNativeTypeStart, &strLen, &pNativeType)))
879                         {
880                             INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_BADMETADATA)); 
881                             break;
882                         }
883                         if (strLen > 0)
884                         {
885                             // Load the type. Use a SString for the string since we need to NULL terminate the string
886                             // that comes from the metadata.
887                             StackSString safeArrayUserDefTypeName(SString::Utf8, (LPCUTF8)pNativeType, strLen);
888                             _ASSERTE((ULONG)(pNativeType + strLen - pNativeTypeStart) == cbNativeTypeStart);
889
890                             // Sadly this may cause a TypeLoadException, which we currently have to swallow.
891                             // This happens with structs that contain fields of class type where the class itself
892                             // refers to the struct in a field.
893                             thElement = ArraySubTypeLoadWorker(safeArrayUserDefTypeName, pModule->GetAssembly());
894                             if (thElement.IsNull())
895                                 break;
896                         }                           
897                     }
898
899                     ArrayMarshalInfo arrayMarshalInfo(amiRuntime);
900                     arrayMarshalInfo.InitForSafeArray(MarshalInfo::MARSHAL_SCENARIO_FIELD, thElement, vtElement, fAnsi);
901
902                     if (!arrayMarshalInfo.IsValid())
903                     {
904                         INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (arrayMarshalInfo.GetErrorResourceId())); 
905                         break;
906                     }
907
908                     INITFIELDMARSHALER(NFT_SAFEARRAY, FieldMarshaler_SafeArray, (arrayMarshalInfo.GetElementVT(), arrayMarshalInfo.GetElementTypeHandle().GetMethodTable()));
909                 }
910                 else if (ntype == NATIVE_TYPE_FIXEDARRAY)
911                 {
912                     // Check for the number of elements. This is required, if not present fail.
913                     if (S_OK != CheckForCompressedData(pNativeTypeStart, pNativeType, cbNativeTypeStart))
914                     {
915                         INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHALFIELD_FIXEDARRAY_NOSIZE));                            
916                         break;
917                     }
918                             
919                     ULONG numElements = CorSigUncompressData(/*modifies*/pNativeType);
920
921                     if (numElements == 0)
922                     {
923                         INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHALFIELD_FIXEDARRAY_ZEROSIZE));                            
924                         break;
925                     }
926                            
927                     // Since these always export to arrays of BSTRs, we don't need to fetch the native type.
928
929                     // Compat: FixedArrays of System.Arrays map to fixed arrays of BSTRs.
930                     INITFIELDMARSHALER(NFT_FIXEDARRAY, FieldMarshaler_FixedArray, (pInternalImport, cl, numElements, VT_BSTR, g_pStringClass));
931                 }
932             }
933 #endif // FEATURE_CLASSIC_COMINTEROP
934             else if (COMDelegate::IsDelegate(thNestedType.GetMethodTable()))
935             {
936                 if (fDefault || ntype == NATIVE_TYPE_FUNC)
937                 {
938                     INITFIELDMARSHALER(NFT_DELEGATE, FieldMarshaler_Delegate, (thNestedType.GetMethodTable()));
939                 }
940                 else
941                 {
942                     INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_DELEGATE));
943                 }
944             } 
945             else if (thNestedType.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__SAFE_HANDLE))))
946             {
947                 if (fDefault) 
948                 {
949                     INITFIELDMARSHALER(NFT_SAFEHANDLE, FieldMarshaler_SafeHandle, ());
950                 }
951                 else 
952                 {
953                     INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_SAFEHANDLE));
954                 }
955             }
956             else if (thNestedType.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__CRITICAL_HANDLE))))
957             {
958                 if (fDefault) 
959                 {
960                     INITFIELDMARSHALER(NFT_CRITICALHANDLE, FieldMarshaler_CriticalHandle, ());
961                 }
962                 else 
963                 {
964                     INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_CRITICALHANDLE));
965                 }
966             }
967             else if (fsig.IsClass(g_StringBufferClassName))
968             {
969                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHALFIELD_NOSTRINGBUILDER));
970             }
971             else if (IsStructMarshalable(thNestedType))
972             {
973                 if (fDefault || ntype == NATIVE_TYPE_STRUCT)
974                 {
975                     INITFIELDMARSHALER(NFT_NESTEDLAYOUTCLASS, FieldMarshaler_NestedLayoutClass, (thNestedType.GetMethodTable()));
976                 }
977                 else
978                 {
979                     INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHALFIELD_LAYOUTCLASS));
980                 }
981             }
982 #ifdef FEATURE_COMINTEROP
983             else if (fIsWinRT)
984             {
985                 // no other reference types are allowed as field types in WinRT
986                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE));
987             }
988             else if (fDefault)
989             {
990                 ItfMarshalInfo itfInfo;
991                 if (FAILED(MarshalInfo::TryGetItfMarshalInfo(thNestedType, FALSE, FALSE, &itfInfo)))
992                 {
993                     INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_BADMANAGED));
994                 }
995                 else
996                 {
997                     INITFIELDMARSHALER(NFT_INTERFACE, FieldMarshaler_Interface, (itfInfo.thClass.GetMethodTable(), itfInfo.thItf.GetMethodTable(), itfInfo.dwFlags));
998                 }
999             }
1000 #endif  // FEATURE_COMINTEROP
1001             break;
1002         }
1003
1004         case ELEMENT_TYPE_SZARRAY:
1005         case ELEMENT_TYPE_ARRAY:
1006         {
1007 #ifdef FEATURE_COMINTEROP
1008             if (fIsWinRT)
1009             {
1010                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE));
1011                 break;
1012             }
1013 #endif // FEATURE_COMINTEROP
1014
1015             // This may cause a TypeLoadException, which we currently seem to have to swallow.
1016             // This happens with structs that contain fields of class type where the class itself
1017             // refers to the struct in a field.
1018             TypeHandle thArray = GetFieldTypeHandleWorker(&fsig);
1019             if (thArray.IsNull() || !thArray.IsArray())
1020                 break;
1021
1022             TypeHandle thElement = thArray.AsArray()->GetArrayElementTypeHandle();
1023             if (thElement.IsNull())
1024                 break;
1025
1026             if (ntype == NATIVE_TYPE_FIXEDARRAY)
1027             {
1028                 CorNativeType elementNativeType = NATIVE_TYPE_DEFAULT;
1029                 
1030                 // The size constant must be specified, if it isn't then the struct can't be marshalled.
1031                 if (S_OK != CheckForCompressedData(pNativeTypeStart, pNativeType, cbNativeTypeStart))
1032                 {
1033                     INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHALFIELD_FIXEDARRAY_NOSIZE));                            
1034                     break;
1035                 }
1036
1037                 // Read the size const, if it's 0, then the struct can't be marshalled.
1038                 ULONG numElements = CorSigUncompressData(pNativeType);            
1039                 if (numElements == 0)
1040                 {
1041                     INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHALFIELD_FIXEDARRAY_ZEROSIZE));                            
1042                     break;
1043                 }
1044
1045                 // The array sub type is optional so extract it if specified.
1046                 if (S_OK == CheckForCompressedData(pNativeTypeStart, pNativeType, cbNativeTypeStart))
1047                     elementNativeType = (CorNativeType)CorSigUncompressData(pNativeType);
1048
1049                 ArrayMarshalInfo arrayMarshalInfo(amiRuntime);
1050                 arrayMarshalInfo.InitForFixedArray(thElement, elementNativeType, fAnsi);
1051
1052                 if (!arrayMarshalInfo.IsValid())
1053                 {
1054                     INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (arrayMarshalInfo.GetErrorResourceId())); 
1055                     break;
1056                 }
1057
1058                 if (arrayMarshalInfo.GetElementVT() == VTHACK_ANSICHAR)
1059                 {
1060                     // We need to special case fixed sized arrays of ANSI chars since the OleVariant code
1061                     // that is used by the generic fixed size array marshaller doesn't support them
1062                     // properly. 
1063                     ReadBestFitCustomAttribute(pInternalImport, cl, &BestFit, &ThrowOnUnmappableChar);
1064                     INITFIELDMARSHALER(NFT_FIXEDCHARARRAYANSI, FieldMarshaler_FixedCharArrayAnsi, (numElements, BestFit, ThrowOnUnmappableChar));
1065                     break;                    
1066                 }
1067                 else
1068                 {
1069                     VARTYPE elementVT = arrayMarshalInfo.GetElementVT();
1070
1071                     INITFIELDMARSHALER(NFT_FIXEDARRAY, FieldMarshaler_FixedArray, (pInternalImport, cl, numElements, elementVT, arrayMarshalInfo.GetElementTypeHandle().GetMethodTable()));
1072                     break;
1073                 }
1074             }
1075 #ifdef FEATURE_CLASSIC_COMINTEROP
1076             else if (fDefault || ntype == NATIVE_TYPE_SAFEARRAY)
1077             {
1078                 VARTYPE vtElement = VT_EMPTY;
1079
1080                 // Check for data remaining in the signature before we attempt to grab some.
1081                 if (S_OK == CheckForCompressedData(pNativeTypeStart, pNativeType, cbNativeTypeStart))
1082                     vtElement = (VARTYPE) (CorSigUncompressData(/*modifies*/pNativeType));
1083
1084                 ArrayMarshalInfo arrayMarshalInfo(amiRuntime);
1085                 arrayMarshalInfo.InitForSafeArray(MarshalInfo::MARSHAL_SCENARIO_FIELD, thElement, vtElement, fAnsi);
1086
1087                 if (!arrayMarshalInfo.IsValid())
1088                 {
1089                     INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (arrayMarshalInfo.GetErrorResourceId())); 
1090                     break;
1091                 }
1092                     
1093                 INITFIELDMARSHALER(NFT_SAFEARRAY, FieldMarshaler_SafeArray, (arrayMarshalInfo.GetElementVT(), arrayMarshalInfo.GetElementTypeHandle().GetMethodTable()));
1094             }
1095 #endif //FEATURE_CLASSIC_COMINTEROP
1096             else
1097             {
1098                 INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHALFIELD_ARRAY));                     
1099             }
1100             break;
1101         }            
1102
1103         case ELEMENT_TYPE_OBJECT:
1104         case ELEMENT_TYPE_STRING:
1105             break;
1106
1107         default:
1108             // let it fall thru as NFT_NONE
1109             break;
1110     }
1111
1112     if (pfwalk->m_nft == NFT_NONE)
1113     {
1114         INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_BADMANAGED));
1115     }
1116 #ifdef FEATURE_COMINTEROP
1117     else if (fIsWinRT && !NFTDataBase[pfwalk->m_nft].m_fWinRTSupported)
1118     {
1119         // the field marshaler we came up with is not supported in WinRT scenarios
1120         ZeroMemory(&pfwalk->m_FieldMarshaler, MAXFIELDMARSHALERSIZE);
1121         INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE));
1122     }
1123 #endif // FEATURE_COMINTEROP
1124 #undef INITFIELDMARSHALER
1125 }
1126 #ifdef _PREFAST_
1127 #pragma warning(pop)
1128 #endif
1129
1130
1131 TypeHandle ArraySubTypeLoadWorker(const SString &strUserDefTypeName, Assembly* pAssembly)
1132 {
1133     CONTRACTL
1134     {
1135         THROWS;
1136         GC_TRIGGERS;
1137         MODE_ANY;
1138         PRECONDITION(CheckPointer(pAssembly));
1139     }
1140     CONTRACTL_END;
1141     
1142     TypeHandle th; 
1143
1144     EX_TRY
1145     {
1146         // Load the user defined type.
1147         StackScratchBuffer utf8Name;
1148         th = TypeName::GetTypeUsingCASearchRules(strUserDefTypeName.GetUTF8(utf8Name), pAssembly);
1149     }
1150     EX_CATCH
1151     {
1152     }
1153     EX_END_CATCH(RethrowTerminalExceptions)
1154     
1155     return th;
1156 }
1157
1158
1159 TypeHandle GetFieldTypeHandleWorker(MetaSig *pFieldSig)
1160 {
1161     CONTRACTL
1162     {
1163         THROWS;
1164         GC_TRIGGERS;
1165         MODE_ANY;
1166         PRECONDITION(CheckPointer(pFieldSig));
1167     }
1168     CONTRACTL_END;
1169
1170     TypeHandle th; 
1171
1172     EX_TRY
1173     {
1174         // Load the user defined type.
1175         th = pFieldSig->GetLastTypeHandleThrowing(ClassLoader::LoadTypes, 
1176                                                   CLASS_LOAD_APPROXPARENTS,
1177                                                   TRUE /*dropGenericArgumentLevel*/);
1178     }
1179     EX_CATCH
1180     {
1181     }
1182     EX_END_CATCH(RethrowTerminalExceptions)
1183
1184     return th;
1185 }
1186
1187
1188 //=======================================================================
1189 // This function returns TRUE if the type passed in is either a value class or a class and if it has layout information 
1190 // and is marshalable. In all other cases it will return FALSE. 
1191 //=======================================================================
1192 BOOL IsStructMarshalable(TypeHandle th)
1193 {
1194     CONTRACTL
1195     {
1196         NOTHROW;
1197         GC_NOTRIGGER;
1198         MODE_ANY;
1199         PRECONDITION(!th.IsNull());
1200     }
1201     CONTRACTL_END;
1202     
1203     if (th.IsBlittable())
1204     {
1205         // th.IsBlittable will return true for arrays of blittable types, however since IsStructMarshalable
1206         // is only supposed to return true for value classes or classes with layout that are marshallable
1207         // we need to return false if the type is an array.
1208         if (th.IsArray())
1209             return FALSE;
1210         else
1211             return TRUE;
1212     }
1213
1214     // Check to see if the type has layout.
1215     if (!th.HasLayout())
1216         return FALSE;
1217
1218     MethodTable *pMT= th.GetMethodTable();
1219     PREFIX_ASSUME(pMT != NULL);
1220     
1221     if (pMT->IsStructMarshalable())
1222         return TRUE;
1223
1224     const FieldMarshaler *pFieldMarshaler = pMT->GetLayoutInfo()->GetFieldMarshalers();
1225     UINT  numReferenceFields              = pMT->GetLayoutInfo()->GetNumCTMFields();
1226
1227     while (numReferenceFields--)
1228     {
1229         if (pFieldMarshaler->GetNStructFieldType() == NFT_ILLEGAL)
1230             return FALSE;
1231
1232         ((BYTE*&)pFieldMarshaler) += MAXFIELDMARSHALERSIZE;
1233     }
1234
1235     return TRUE;
1236 }
1237
1238 #ifdef _DEBUG
1239 BOOL IsFixedBuffer(mdFieldDef field, IMDInternalImport *pInternalImport)
1240 {
1241     HRESULT hr = pInternalImport->GetCustomAttributeByName(field, g_FixedBufferAttribute, NULL, NULL);
1242
1243     return hr == S_OK ? TRUE : FALSE;
1244 }
1245 #endif
1246
1247
1248 //=======================================================================
1249 // Called from the clsloader to load up and summarize the field metadata
1250 // for layout classes.
1251 //
1252 // Warning: This function can load other classes (esp. for nested structs.)
1253 //=======================================================================
1254 #ifdef _PREFAST_
1255 #pragma warning(push)
1256 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
1257 #endif
1258 VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
1259    mdTypeDef      cl,               // cl of the NStruct being loaded
1260    BYTE           packingSize,      // packing size (from @dll.struct)
1261    BYTE           nlType,           // nltype (from @dll.struct)
1262 #ifdef FEATURE_COMINTEROP
1263    BOOL           isWinRT,          // Is the type a WinRT type
1264 #endif // FEATURE_COMINTEROP
1265    BOOL           fExplicitOffsets, // explicit offsets?
1266    MethodTable   *pParentMT,        // the loaded superclass
1267    ULONG          cMembers,         // total number of members (methods + fields)
1268    HENUMInternal *phEnumField,      // enumerator for field
1269    Module        *pModule,          // Module that defines the scope, loader and heap (for allocate FieldMarshalers)
1270    const SigTypeContext *pTypeContext,          // Type parameters for NStruct being loaded
1271    EEClassLayoutInfo    *pEEClassLayoutInfoOut, // caller-allocated structure to fill in.
1272    LayoutRawFieldInfo   *pInfoArrayOut,         // caller-allocated array to fill in.  Needs room for cMember+1 elements
1273    LoaderAllocator      *pAllocator,
1274    AllocMemTracker      *pamTracker
1275 )
1276 {
1277     CONTRACTL
1278     {
1279         THROWS;
1280         GC_TRIGGERS;
1281         MODE_ANY;
1282         INJECT_FAULT(COMPlusThrowOM());
1283         PRECONDITION(CheckPointer(pModule));
1284     }
1285     CONTRACTL_END;
1286
1287     HRESULT             hr;
1288     MD_CLASS_LAYOUT     classlayout;
1289     mdFieldDef          fd;
1290     ULONG               ulOffset;
1291     ULONG cFields = 0;
1292
1293     // Running tote - if anything in this type disqualifies it from being ManagedSequential, somebody will set this to TRUE by the the time
1294     // function exits.
1295     BOOL                fDisqualifyFromManagedSequential = FALSE; 
1296
1297     // Internal interface for the NStruct being loaded.
1298     IMDInternalImport *pInternalImport = pModule->GetMDImport();
1299
1300
1301 #ifdef _DEBUG
1302     LPCUTF8 szName; 
1303     LPCUTF8 szNamespace; 
1304     if (FAILED(pInternalImport->GetNameOfTypeDef(cl, &szName, &szNamespace)))
1305     {
1306         szName = szNamespace = "Invalid TypeDef record";
1307     }
1308     
1309     if (g_pConfig->ShouldBreakOnStructMarshalSetup(szName))
1310         CONSISTENCY_CHECK_MSGF(false, ("BreakOnStructMarshalSetup: '%s' ", szName));
1311 #endif
1312
1313
1314     // Check if this type might be ManagedSequential. Only valuetypes marked Sequential can be
1315     // ManagedSequential. Other issues checked below might also disqualify the type.
1316     if ( (!fExplicitOffsets) &&    // Is it marked sequential?
1317          (pParentMT && (pParentMT->IsValueTypeClass() || pParentMT->IsManagedSequential()))  // Is it a valuetype or derived from a qualifying valuetype?
1318        )
1319     {
1320         // Type qualifies so far... need do nothing.
1321     }
1322     else
1323     {
1324         fDisqualifyFromManagedSequential = TRUE;
1325     }
1326
1327
1328     BOOL fHasNonTrivialParent = pParentMT &&
1329                                 !pParentMT->IsObjectClass() &&
1330                                 !pParentMT->IsValueTypeClass();
1331
1332
1333     //====================================================================
1334     // First, some validation checks.
1335     //====================================================================
1336     _ASSERTE(!(fHasNonTrivialParent && !(pParentMT->HasLayout())));
1337
1338     hr = pInternalImport->GetClassLayoutInit(cl, &classlayout);
1339     if (FAILED(hr))
1340     {
1341         COMPlusThrowHR(hr, BFA_CANT_GET_CLASSLAYOUT);
1342     }
1343
1344     pEEClassLayoutInfoOut->m_numCTMFields        = fHasNonTrivialParent ? pParentMT->GetLayoutInfo()->m_numCTMFields : 0;
1345     pEEClassLayoutInfoOut->SetFieldMarshalers(NULL);
1346     pEEClassLayoutInfoOut->SetIsBlittable(TRUE);
1347     if (fHasNonTrivialParent)
1348         pEEClassLayoutInfoOut->SetIsBlittable(pParentMT->IsBlittable());
1349     pEEClassLayoutInfoOut->SetIsZeroSized(FALSE);    
1350     pEEClassLayoutInfoOut->SetHasExplicitSize(FALSE);
1351     pEEClassLayoutInfoOut->m_cbPackingSize = packingSize;
1352
1353     LayoutRawFieldInfo *pfwalk = pInfoArrayOut;
1354     
1355     S_UINT32 cbSortArraySize = S_UINT32(cMembers) * S_UINT32(sizeof(LayoutRawFieldInfo *));
1356     if (cbSortArraySize.IsOverflow())
1357     {
1358         ThrowHR(COR_E_TYPELOAD);
1359     }
1360     LayoutRawFieldInfo **pSortArray = (LayoutRawFieldInfo **)_alloca(cbSortArraySize.Value());
1361     LayoutRawFieldInfo **pSortArrayEnd = pSortArray;
1362     
1363     ULONG maxRid = pInternalImport->GetCountWithTokenKind(mdtFieldDef);
1364     
1365     
1366     //=====================================================================
1367     // Phase 1: Figure out the NFT of each field based on both the CLR
1368     // signature of the field and the FieldMarshaler metadata. 
1369     //=====================================================================
1370     BOOL fParentHasLayout = pParentMT && pParentMT->HasLayout();
1371     UINT32 cbAdjustedParentLayoutNativeSize = 0;
1372     EEClassLayoutInfo *pParentLayoutInfo = NULL;;
1373     if (fParentHasLayout)
1374     {
1375         pParentLayoutInfo = pParentMT->GetLayoutInfo();
1376         // Treat base class as an initial member.
1377         cbAdjustedParentLayoutNativeSize = pParentLayoutInfo->GetNativeSize();
1378         // If the parent was originally a zero-sized explicit type but
1379         // got bumped up to a size of 1 for compatibility reasons, then
1380         // we need to remove the padding, but ONLY for inheritance situations.
1381         if (pParentLayoutInfo->IsZeroSized()) {
1382             CONSISTENCY_CHECK(cbAdjustedParentLayoutNativeSize == 1);
1383             cbAdjustedParentLayoutNativeSize = 0;
1384         }
1385     }
1386
1387     ULONG i;
1388     for (i = 0; pInternalImport->EnumNext(phEnumField, &fd); i++)
1389     {
1390         DWORD dwFieldAttrs;
1391         ULONG rid = RidFromToken(fd);
1392
1393         if((rid == 0)||(rid > maxRid))
1394         {
1395             COMPlusThrowHR(COR_E_TYPELOAD, BFA_BAD_FIELD_TOKEN);
1396         }
1397
1398         IfFailThrow(pInternalImport->GetFieldDefProps(fd, &dwFieldAttrs));
1399         
1400         PCCOR_SIGNATURE pNativeType = NULL;
1401         ULONG cbNativeType;
1402         // We ignore marshaling data attached to statics and literals,
1403         // since these do not contribute to instance data.
1404         if (!IsFdStatic(dwFieldAttrs) && !IsFdLiteral(dwFieldAttrs))
1405         {
1406             PCCOR_SIGNATURE pCOMSignature;
1407             ULONG       cbCOMSignature;
1408
1409             if (IsFdHasFieldMarshal(dwFieldAttrs))
1410             {
1411                 hr = pInternalImport->GetFieldMarshal(fd, &pNativeType, &cbNativeType);
1412                 if (FAILED(hr))
1413                     cbNativeType = 0;
1414             }
1415             else
1416                 cbNativeType = 0;
1417             
1418             IfFailThrow(pInternalImport->GetSigOfFieldDef(fd,&cbCOMSignature, &pCOMSignature));
1419             
1420             IfFailThrow(::validateTokenSig(fd,pCOMSignature,cbCOMSignature,dwFieldAttrs,pInternalImport));
1421             
1422             // fill the appropriate entry in pInfoArrayOut
1423             pfwalk->m_MD = fd;
1424             pfwalk->m_nft = NULL;
1425             pfwalk->m_offset = (UINT32) -1;
1426             pfwalk->m_sequence = 0;
1427
1428 #ifdef _DEBUG
1429             LPCUTF8 szFieldName;
1430             if (FAILED(pInternalImport->GetNameOfFieldDef(fd, &szFieldName)))
1431             {
1432                 szFieldName = "Invalid FieldDef record";
1433             }
1434 #endif
1435
1436             ParseNativeTypeFlags flags = ParseNativeTypeFlag_None;
1437 #ifdef FEATURE_COMINTEROP
1438             if (isWinRT)
1439                 flags |= ParseNativeTypeFlag_IsWinRT;
1440             else // WinRT types have nlType == nltAnsi but should be treated as Unicode
1441 #endif // FEATURE_COMINTEROP
1442             if (nlType == nltAnsi)
1443                 flags |=  ParseNativeTypeFlag_IsAnsi;
1444
1445             ParseNativeType(pModule,
1446                             pCOMSignature,
1447                             cbCOMSignature,
1448                             flags,
1449                             pfwalk,
1450                             pNativeType,
1451                             cbNativeType,
1452                             pInternalImport,
1453                             cl,
1454                             pTypeContext,
1455                             &fDisqualifyFromManagedSequential
1456 #ifdef _DEBUG
1457                             ,
1458                             szNamespace,
1459                             szName,
1460                             szFieldName
1461 #endif
1462                                 );
1463
1464
1465             //<TODO>@nice: This is obviously not the place to bury this logic.
1466             // We're replacing NFT's with MARSHAL_TYPES_* in the near future
1467             // so this isn't worth perfecting.</TODO>
1468
1469             BOOL    resetBlittable = TRUE;
1470
1471             // if it's a simple copy...
1472             if (pfwalk->m_nft == NFT_COPY1    ||
1473                 pfwalk->m_nft == NFT_COPY2    ||
1474                 pfwalk->m_nft == NFT_COPY4    ||
1475                 pfwalk->m_nft == NFT_COPY8)
1476             {
1477                 resetBlittable = FALSE;
1478             }
1479
1480             // Or if it's a nested value class that is itself blittable...
1481             if (pfwalk->m_nft == NFT_NESTEDVALUECLASS)
1482             {
1483                 FieldMarshaler *pFM = (FieldMarshaler*)&(pfwalk->m_FieldMarshaler);
1484                 _ASSERTE(pFM->IsNestedValueClassMarshaler());
1485
1486                 if (((FieldMarshaler_NestedValueClass *) pFM)->IsBlittable())
1487                     resetBlittable = FALSE;
1488             }
1489
1490             // ...Otherwise, this field prevents blitting
1491             if (resetBlittable)
1492                 pEEClassLayoutInfoOut->SetIsBlittable(FALSE);
1493
1494             cFields++;
1495             pfwalk++;
1496         }
1497     }
1498
1499     _ASSERTE(i == cMembers);
1500
1501     // NULL out the last entry
1502     pfwalk->m_MD = mdFieldDefNil;
1503     
1504     
1505     //
1506     // fill in the layout information 
1507     //
1508     
1509     // pfwalk points to the beginging of the array
1510     pfwalk = pInfoArrayOut;
1511
1512     while (SUCCEEDED(hr = pInternalImport->GetClassLayoutNext(
1513                                      &classlayout,
1514                                      &fd,
1515                                      &ulOffset)) &&
1516                                      fd != mdFieldDefNil)
1517     {
1518         // watch for the last entry: must be mdFieldDefNil
1519         while ((mdFieldDefNil != pfwalk->m_MD)&&(pfwalk->m_MD < fd))
1520             pfwalk++;
1521
1522         // if we haven't found a matching token, it must be a static field with layout -- ignore it
1523         if(pfwalk->m_MD != fd) continue;
1524
1525         if (!fExplicitOffsets)
1526         {
1527             // ulOffset is the sequence
1528             pfwalk->m_sequence = ulOffset;
1529         }
1530         else
1531         {
1532             // ulOffset is the explicit offset
1533             pfwalk->m_offset = ulOffset;
1534             pfwalk->m_sequence = (ULONG) -1;
1535
1536             // Treat base class as an initial member.
1537             if (!SafeAddUINT32(&(pfwalk->m_offset), cbAdjustedParentLayoutNativeSize))
1538                 COMPlusThrowOM();
1539         }
1540     }
1541     IfFailThrow(hr);
1542
1543     // now sort the array
1544     if (!fExplicitOffsets)
1545     { 
1546         // sort sequential by ascending sequence
1547         for (i = 0; i < cFields; i++)
1548         {
1549             LayoutRawFieldInfo**pSortWalk = pSortArrayEnd;
1550             while (pSortWalk != pSortArray)
1551             {
1552                 if (pInfoArrayOut[i].m_sequence >= (*(pSortWalk-1))->m_sequence)
1553                     break;
1554
1555                 pSortWalk--;
1556             }
1557
1558             // pSortWalk now points to the target location for new FieldInfo.
1559             MoveMemory(pSortWalk + 1, pSortWalk, (pSortArrayEnd - pSortWalk) * sizeof(LayoutRawFieldInfo*));
1560             *pSortWalk = &pInfoArrayOut[i];
1561             pSortArrayEnd++;
1562         }
1563     }
1564     else // no sorting for explicit layout
1565     {
1566         for (i = 0; i < cFields; i++)
1567         {
1568             if(pInfoArrayOut[i].m_MD != mdFieldDefNil)
1569             {
1570                 if (pInfoArrayOut[i].m_offset == (UINT32)-1)
1571                 {
1572                     LPCUTF8 szFieldName;
1573                     if (FAILED(pInternalImport->GetNameOfFieldDef(pInfoArrayOut[i].m_MD, &szFieldName)))
1574                     {
1575                         szFieldName = "Invalid FieldDef record";
1576                     }
1577                     pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, 
1578                                                                    cl,
1579                                                                    szFieldName,
1580                                                                    IDS_CLASSLOAD_NSTRUCT_EXPLICIT_OFFSET);
1581                 }
1582                 else if ((INT)pInfoArrayOut[i].m_offset < 0)
1583                 {
1584                     LPCUTF8 szFieldName;
1585                     if (FAILED(pInternalImport->GetNameOfFieldDef(pInfoArrayOut[i].m_MD, &szFieldName)))
1586                     {
1587                         szFieldName = "Invalid FieldDef record";
1588                     }
1589                     pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, 
1590                                                                    cl,
1591                                                                    szFieldName,
1592                                                                    IDS_CLASSLOAD_NSTRUCT_NEGATIVE_OFFSET);
1593                 }
1594             }
1595                 
1596             *pSortArrayEnd = &pInfoArrayOut[i];
1597             pSortArrayEnd++;
1598         }
1599     }
1600
1601     //=====================================================================
1602     // Phase 2: Compute the native size (in bytes) of each field.
1603     // Store this in pInfoArrayOut[].cbNativeSize;
1604     //=====================================================================
1605
1606     // Now compute the native size of each field
1607     for (pfwalk = pInfoArrayOut; pfwalk->m_MD != mdFieldDefNil; pfwalk++)
1608     {
1609         UINT8 nft = pfwalk->m_nft;
1610         pEEClassLayoutInfoOut->m_numCTMFields++;
1611
1612         // If the NFT's size never changes, it is stored in the database.
1613         UINT32 cbNativeSize = NFTDataBase[nft].m_cbNativeSize;
1614
1615         if (cbNativeSize == 0)
1616         {
1617             // Size of 0 means NFT's size is variable, so we have to figure it
1618             // out case by case.
1619             cbNativeSize = ((FieldMarshaler*)&(pfwalk->m_FieldMarshaler))->NativeSize();
1620         }
1621         pfwalk->m_cbNativeSize = cbNativeSize;
1622     }
1623
1624     if (pEEClassLayoutInfoOut->m_numCTMFields)
1625     {
1626         pEEClassLayoutInfoOut->SetFieldMarshalers((FieldMarshaler*)(pamTracker->Track(pAllocator->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(MAXFIELDMARSHALERSIZE) * S_SIZE_T(pEEClassLayoutInfoOut->m_numCTMFields)))));
1627
1628         // Bring in the parent's fieldmarshalers
1629         if (fHasNonTrivialParent)
1630         {
1631             CONSISTENCY_CHECK(fParentHasLayout);
1632             PREFAST_ASSUME(pParentLayoutInfo != NULL);  // See if (fParentHasLayout) branch above
1633
1634             UINT numChildCTMFields = pEEClassLayoutInfoOut->m_numCTMFields - pParentLayoutInfo->m_numCTMFields;
1635
1636             BYTE *pParentCTMFieldSrcArray = (BYTE*)pParentLayoutInfo->GetFieldMarshalers();
1637             BYTE *pParentCTMFieldDestArray = ((BYTE*)pEEClassLayoutInfoOut->GetFieldMarshalers()) + MAXFIELDMARSHALERSIZE*numChildCTMFields;
1638
1639             for (UINT parentCTMFieldIndex = 0; parentCTMFieldIndex < pParentLayoutInfo->m_numCTMFields; parentCTMFieldIndex++)
1640             {
1641                 FieldMarshaler *pParentCTMFieldSrc = (FieldMarshaler *)(pParentCTMFieldSrcArray + MAXFIELDMARSHALERSIZE*parentCTMFieldIndex);
1642                 FieldMarshaler *pParentCTMFieldDest = (FieldMarshaler *)(pParentCTMFieldDestArray + MAXFIELDMARSHALERSIZE*parentCTMFieldIndex);
1643
1644                 pParentCTMFieldSrc->CopyTo(pParentCTMFieldDest, MAXFIELDMARSHALERSIZE);
1645             }
1646         }
1647
1648     }
1649
1650
1651     //=====================================================================
1652     // Phase 3: If FieldMarshaler requires autooffsetting, compute the offset
1653     // of each field and the size of the total structure. We do the layout
1654     // according to standard VC layout rules:
1655     //
1656     //   Each field has an alignment requirement. The alignment-requirement
1657     //   of a scalar field is the smaller of its size and the declared packsize.
1658     //   The alignment-requirement of a struct field is the smaller of the
1659     //   declared packsize and the largest of the alignment-requirement
1660     //   of its fields. The alignment requirement of an array is that
1661     //   of one of its elements.
1662     //
1663     //   In addition, each struct gets padding at the end to ensure
1664     //   that an array of such structs contain no unused space between
1665     //   elements.
1666     //=====================================================================
1667     {
1668         BYTE   LargestAlignmentRequirement = 1;
1669         UINT32 cbCurOffset = 0;
1670
1671         // Treat base class as an initial member.
1672         if (!SafeAddUINT32(&cbCurOffset, cbAdjustedParentLayoutNativeSize))
1673             COMPlusThrowOM();
1674
1675         if (fParentHasLayout)
1676         {
1677             BYTE alignmentRequirement;
1678             
1679             alignmentRequirement = min(packingSize, pParentLayoutInfo->GetLargestAlignmentRequirementOfAllMembers());
1680     
1681             LargestAlignmentRequirement = max(LargestAlignmentRequirement, alignmentRequirement);                                          
1682         }
1683
1684         // Start with the size inherited from the parent (if any).
1685         unsigned calcTotalSize = cbAdjustedParentLayoutNativeSize;
1686      
1687         LayoutRawFieldInfo **pSortWalk;
1688         for (pSortWalk = pSortArray, i=cFields; i; i--, pSortWalk++)
1689         {
1690             pfwalk = *pSortWalk;
1691     
1692             BYTE alignmentRequirement = static_cast<BYTE>(((FieldMarshaler*)&(pfwalk->m_FieldMarshaler))->AlignmentRequirement());
1693             if (!(alignmentRequirement == 1 ||
1694                      alignmentRequirement == 2 ||
1695                      alignmentRequirement == 4 ||
1696                   alignmentRequirement == 8 ||
1697                   alignmentRequirement == 16 ||
1698                   alignmentRequirement == 32))
1699             {
1700                 COMPlusThrowHR(COR_E_INVALIDPROGRAM, BFA_METADATA_CORRUPT);
1701             }
1702     
1703             alignmentRequirement = min(alignmentRequirement, packingSize);
1704     
1705             LargestAlignmentRequirement = max(LargestAlignmentRequirement, alignmentRequirement);
1706     
1707             // This assert means I forgot to special-case some NFT in the
1708             // above switch.
1709             _ASSERTE(alignmentRequirement <= 32);
1710     
1711             // Check if this field is overlapped with other(s)
1712             pfwalk->m_fIsOverlapped = FALSE;
1713             if (fExplicitOffsets) {
1714                 LayoutRawFieldInfo *pfwalk1;
1715                 DWORD dwBegin = pfwalk->m_offset;
1716                 DWORD dwEnd = dwBegin+pfwalk->m_cbNativeSize;
1717                 for (pfwalk1 = pInfoArrayOut; pfwalk1 < pfwalk; pfwalk1++)
1718                 {
1719                     if((pfwalk1->m_offset >= dwEnd) || (pfwalk1->m_offset+pfwalk1->m_cbNativeSize <= dwBegin)) continue;
1720                     pfwalk->m_fIsOverlapped = TRUE;
1721                     pfwalk1->m_fIsOverlapped = TRUE;
1722                 }
1723             }
1724             else
1725             {
1726                 // Insert enough padding to align the current data member.
1727                 while (cbCurOffset % alignmentRequirement)
1728                 {
1729                     if (!SafeAddUINT32(&cbCurOffset, 1))
1730                         COMPlusThrowOM();
1731                 }
1732     
1733                 // Insert current data member.
1734                 pfwalk->m_offset = cbCurOffset;
1735     
1736                 // if we overflow we will catch it below
1737                 cbCurOffset += pfwalk->m_cbNativeSize;
1738             } 
1739     
1740             unsigned fieldEnd = pfwalk->m_offset + pfwalk->m_cbNativeSize;
1741             if (fieldEnd < pfwalk->m_offset)
1742                 COMPlusThrowOM();
1743     
1744                 // size of the structure is the size of the last field.  
1745             if (fieldEnd > calcTotalSize)
1746                 calcTotalSize = fieldEnd;
1747         }
1748     
1749         ULONG clstotalsize = 0;
1750         if (FAILED(pInternalImport->GetClassTotalSize(cl, &clstotalsize)))
1751         {
1752             clstotalsize = 0;
1753         }
1754         
1755         if (clstotalsize != 0)
1756         {
1757             if (!SafeAddULONG(&clstotalsize, (ULONG)cbAdjustedParentLayoutNativeSize))
1758                 COMPlusThrowOM();
1759     
1760             // size must be large enough to accomodate layout. If not, we use the layout size instead.
1761             if (clstotalsize < calcTotalSize)
1762             {
1763                 clstotalsize = calcTotalSize;
1764             }
1765             calcTotalSize = clstotalsize;   // use the size they told us 
1766         } 
1767         else
1768         {
1769             // The did not give us an explict size, so lets round up to a good size (for arrays) 
1770             while (calcTotalSize % LargestAlignmentRequirement != 0)
1771             {
1772                 if (!SafeAddUINT32(&calcTotalSize, 1))
1773                     COMPlusThrowOM();
1774             }
1775         }
1776         
1777         // We'll cap the total native size at a (somewhat) arbitrary limit to ensure
1778         // that we don't expose some overflow bug later on.
1779         if (calcTotalSize >= MAX_SIZE_FOR_INTEROP)
1780             COMPlusThrowOM();
1781
1782         // This is a zero-sized struct - need to record the fact and bump it up to 1.
1783         if (calcTotalSize == 0)
1784         {
1785             pEEClassLayoutInfoOut->SetIsZeroSized(TRUE);
1786             calcTotalSize = 1;
1787         }
1788     
1789         pEEClassLayoutInfoOut->m_cbNativeSize = calcTotalSize;
1790     
1791         // The packingSize acts as a ceiling on all individual alignment
1792         // requirements so it follows that the largest alignment requirement
1793         // is also capped.
1794         _ASSERTE(LargestAlignmentRequirement <= packingSize);
1795         pEEClassLayoutInfoOut->m_LargestAlignmentRequirementOfAllMembers = LargestAlignmentRequirement;
1796     }
1797
1798
1799
1800     //=====================================================================
1801     // Phase 4: Now we do the same thing again for managedsequential layout.
1802     //=====================================================================
1803     if (!fDisqualifyFromManagedSequential)
1804     {
1805         BYTE   LargestAlignmentRequirement = 1;
1806         UINT32 cbCurOffset = 0;
1807     
1808         if (pParentMT && pParentMT->IsManagedSequential())
1809         {
1810             // Treat base class as an initial member.
1811             if (!SafeAddUINT32(&cbCurOffset, pParentMT->GetNumInstanceFieldBytes()))
1812                 COMPlusThrowOM();
1813     
1814             BYTE alignmentRequirement = 0;
1815                 
1816             alignmentRequirement = min(packingSize, pParentLayoutInfo->m_ManagedLargestAlignmentRequirementOfAllMembers);
1817     
1818             LargestAlignmentRequirement = max(LargestAlignmentRequirement, alignmentRequirement);                                          
1819         }
1820     
1821         // The current size of the structure as a whole, we start at 1, because we disallow 0 sized structures.
1822         // NOTE: We do not need to do the same checking for zero-sized types as phase 3 because only ValueTypes
1823         //       can be ManagedSequential and ValueTypes can not be inherited from.
1824         unsigned calcTotalSize = 1;
1825      
1826         LayoutRawFieldInfo **pSortWalk;
1827         for (pSortWalk = pSortArray, i=cFields; i; i--, pSortWalk++)
1828         {
1829             pfwalk = *pSortWalk;
1830     
1831             BYTE alignmentRequirement = ((BYTE)(pfwalk->m_managedAlignmentReq));
1832             if (!(alignmentRequirement == 1 ||
1833                      alignmentRequirement == 2 ||
1834                      alignmentRequirement == 4 ||
1835                   alignmentRequirement == 8 ||
1836                   alignmentRequirement == 16 ||
1837                   alignmentRequirement == 32))
1838             {
1839                 COMPlusThrowHR(COR_E_INVALIDPROGRAM, BFA_METADATA_CORRUPT);
1840             }
1841             
1842             alignmentRequirement = min(alignmentRequirement, packingSize);
1843             
1844             LargestAlignmentRequirement = max(LargestAlignmentRequirement, alignmentRequirement);
1845             
1846             _ASSERTE(alignmentRequirement <= 32);
1847             
1848             // Insert enough padding to align the current data member.
1849             while (cbCurOffset % alignmentRequirement)
1850             {
1851                 if (!SafeAddUINT32(&cbCurOffset, 1))
1852                     COMPlusThrowOM();
1853             }
1854             
1855             // Insert current data member.
1856             pfwalk->m_managedOffset = cbCurOffset;
1857             
1858             // if we overflow we will catch it below
1859             cbCurOffset += pfwalk->m_managedSize;
1860             
1861             unsigned fieldEnd = pfwalk->m_managedOffset + pfwalk->m_managedSize;
1862             if (fieldEnd < pfwalk->m_managedOffset)
1863                 COMPlusThrowOM();
1864             
1865                 // size of the structure is the size of the last field.  
1866             if (fieldEnd > calcTotalSize)
1867                 calcTotalSize = fieldEnd;
1868             
1869 #ifdef _DEBUG
1870             // @perf: If the type is blittable, the managed and native layouts have to be identical
1871             // so they really shouldn't be calculated twice. Until this code has been well tested and
1872             // stabilized, however, it is useful to compute both and assert that they are equal in the blittable
1873             // case.
1874             if (pEEClassLayoutInfoOut->IsBlittable())
1875             {
1876                 _ASSERTE(pfwalk->m_managedOffset == pfwalk->m_offset);
1877                 _ASSERTE(pfwalk->m_managedSize   == pfwalk->m_cbNativeSize);
1878             }
1879 #endif
1880         } //for
1881         
1882         ULONG clstotalsize = 0;
1883         if (FAILED(pInternalImport->GetClassTotalSize(cl, &clstotalsize)))
1884         {
1885             clstotalsize = 0;
1886         }
1887         
1888         if (clstotalsize != 0)
1889         {
1890             pEEClassLayoutInfoOut->SetHasExplicitSize(TRUE);
1891             
1892             if (pParentMT && pParentMT->IsManagedSequential())
1893             {
1894                 // Treat base class as an initial member.
1895                 UINT32 parentSize = pParentMT->GetNumInstanceFieldBytes();
1896                 if (!SafeAddULONG(&clstotalsize, parentSize))
1897                     COMPlusThrowOM();
1898             }
1899     
1900             // size must be large enough to accomodate layout. If not, we use the layout size instead.
1901             if (clstotalsize < calcTotalSize)
1902             {
1903                 clstotalsize = calcTotalSize;
1904             }
1905             calcTotalSize = clstotalsize;   // use the size they told us 
1906         } 
1907         else
1908         {
1909             // The did not give us an explict size, so lets round up to a good size (for arrays) 
1910             while (calcTotalSize % LargestAlignmentRequirement != 0)
1911             {
1912                 if (!SafeAddUINT32(&calcTotalSize, 1))
1913                     COMPlusThrowOM();
1914             }
1915         } 
1916     
1917         pEEClassLayoutInfoOut->m_cbManagedSize = calcTotalSize;
1918
1919         // The packingSize acts as a ceiling on all individual alignment
1920         // requirements so it follows that the largest alignment requirement
1921         // is also capped.
1922         _ASSERTE(LargestAlignmentRequirement <= packingSize);
1923         pEEClassLayoutInfoOut->m_ManagedLargestAlignmentRequirementOfAllMembers = LargestAlignmentRequirement;
1924
1925 #ifdef _DEBUG
1926             // @perf: If the type is blittable, the managed and native layouts have to be identical
1927             // so they really shouldn't be calculated twice. Until this code has been well tested and
1928             // stabilized, however, it is useful to compute both and assert that they are equal in the blittable
1929             // case.
1930             if (pEEClassLayoutInfoOut->IsBlittable())
1931             {
1932                 _ASSERTE(pEEClassLayoutInfoOut->m_cbManagedSize == pEEClassLayoutInfoOut->m_cbNativeSize);
1933                 _ASSERTE(pEEClassLayoutInfoOut->m_ManagedLargestAlignmentRequirementOfAllMembers == pEEClassLayoutInfoOut->m_LargestAlignmentRequirementOfAllMembers);
1934             }
1935 #endif
1936     } //if
1937
1938     pEEClassLayoutInfoOut->SetIsManagedSequential(!fDisqualifyFromManagedSequential);
1939
1940 #ifdef _DEBUG
1941     {
1942         BOOL illegalMarshaler = FALSE;
1943         
1944         LOG((LF_INTEROP, LL_INFO100000, "\n\n"));
1945         LOG((LF_INTEROP, LL_INFO100000, "%s.%s\n", szNamespace, szName));
1946         LOG((LF_INTEROP, LL_INFO100000, "Packsize      = %lu\n", (ULONG)packingSize));
1947         LOG((LF_INTEROP, LL_INFO100000, "Max align req = %lu\n", (ULONG)(pEEClassLayoutInfoOut->m_LargestAlignmentRequirementOfAllMembers)));
1948         LOG((LF_INTEROP, LL_INFO100000, "----------------------------\n"));
1949         for (pfwalk = pInfoArrayOut; pfwalk->m_MD != mdFieldDefNil; pfwalk++)
1950         {
1951             LPCUTF8 fieldname;
1952             if (FAILED(pInternalImport->GetNameOfFieldDef(pfwalk->m_MD, &fieldname)))
1953             {
1954                 fieldname = "??";
1955             }
1956             LOG((LF_INTEROP, LL_INFO100000, "+%-5lu  ", (ULONG)(pfwalk->m_offset)));
1957             LOG((LF_INTEROP, LL_INFO100000, "%s", fieldname));
1958             LOG((LF_INTEROP, LL_INFO100000, "\n"));
1959
1960             if (((FieldMarshaler*)&pfwalk->m_FieldMarshaler)->GetNStructFieldType() == NFT_ILLEGAL)
1961                 illegalMarshaler = TRUE;             
1962         }
1963
1964         // If we are dealing with a non trivial parent, determine if it has any illegal marshallers.
1965         if (fHasNonTrivialParent)
1966         {
1967             FieldMarshaler *pParentFM = pParentMT->GetLayoutInfo()->GetFieldMarshalers();
1968             for (i = 0; i < pParentMT->GetLayoutInfo()->m_numCTMFields; i++)
1969             {
1970                 if (pParentFM->GetNStructFieldType() == NFT_ILLEGAL)
1971                     illegalMarshaler = TRUE;                                 
1972                 ((BYTE*&)pParentFM) += MAXFIELDMARSHALERSIZE;
1973             }
1974         }
1975         
1976         LOG((LF_INTEROP, LL_INFO100000, "+%-5lu   EOS\n", (ULONG)(pEEClassLayoutInfoOut->m_cbNativeSize)));
1977         LOG((LF_INTEROP, LL_INFO100000, "Allocated %d %s field marshallers for %s.%s\n", pEEClassLayoutInfoOut->m_numCTMFields, (illegalMarshaler ? "pointless" : "usable"), szNamespace, szName));
1978     }
1979 #endif
1980     return;
1981 }
1982 #ifdef _PREFAST_
1983 #pragma warning(pop)
1984 #endif
1985
1986
1987 #ifndef CROSSGEN_COMPILE
1988
1989 //=======================================================================
1990 // For each reference-typed FieldMarshaler field, marshals the current CLR value
1991 // to a new native instance and stores it in the fixed portion of the FieldMarshaler.
1992 //
1993 // This function does not attempt to delete the native value that it overwrites.
1994 //
1995 // If there is a SafeHandle field, ppCleanupWorkListOnStack must be non-null, otherwise
1996 // InvalidOperationException is thrown.
1997 //=======================================================================
1998 VOID LayoutUpdateNative(LPVOID *ppProtectedManagedData, SIZE_T offsetbias, MethodTable *pMT, BYTE* pNativeData, OBJECTREF *ppCleanupWorkListOnStack)
1999 {       
2000     CONTRACTL
2001     {
2002         THROWS;
2003         GC_TRIGGERS;
2004         MODE_COOPERATIVE;
2005         PRECONDITION(CheckPointer(pMT));
2006     }
2007     CONTRACTL_END;
2008     
2009     FieldMarshaler* pFM                   = pMT->GetLayoutInfo()->GetFieldMarshalers();
2010     UINT  numReferenceFields              = pMT->GetLayoutInfo()->GetNumCTMFields();
2011     
2012     OBJECTREF pCLRValue    = NULL;
2013     LPVOID scalar           = NULL;
2014     
2015     GCPROTECT_BEGIN(pCLRValue)
2016     GCPROTECT_BEGININTERIOR(scalar)
2017     {
2018         g_IBCLogger.LogFieldMarshalersReadAccess(pMT);
2019
2020         while (numReferenceFields--)
2021         {
2022             pFM->Restore();
2023
2024             DWORD internalOffset = pFM->GetFieldDesc()->GetOffset();
2025
2026             if (pFM->IsScalarMarshaler())
2027             {
2028                 scalar = (LPVOID)(internalOffset + offsetbias + (BYTE*)(*ppProtectedManagedData));
2029                 // Note this will throw for FieldMarshaler_Illegal
2030                 pFM->ScalarUpdateNative(scalar, pNativeData + pFM->GetExternalOffset() );
2031                 
2032             }
2033             else if (pFM->IsNestedValueClassMarshaler())
2034             {
2035                 pFM->NestedValueClassUpdateNative((const VOID **)ppProtectedManagedData, internalOffset + offsetbias, pNativeData + pFM->GetExternalOffset(),
2036                     ppCleanupWorkListOnStack);
2037             }
2038             else
2039             {
2040                 pCLRValue = *(OBJECTREF*)(internalOffset + offsetbias + (BYTE*)(*ppProtectedManagedData));
2041                 pFM->UpdateNative(&pCLRValue, pNativeData + pFM->GetExternalOffset(), ppCleanupWorkListOnStack);
2042                 SetObjectReferenceUnchecked( (OBJECTREF*) (internalOffset + offsetbias + (BYTE*)(*ppProtectedManagedData)), pCLRValue);
2043             }
2044
2045             // The cleanup work list is not used to clean up the native contents. It is used
2046             // to handle cleanup of any additional resources the FieldMarshalers allocate.
2047
2048             ((BYTE*&)pFM) += MAXFIELDMARSHALERSIZE;
2049         }
2050     }
2051     GCPROTECT_END();
2052     GCPROTECT_END();
2053 }
2054
2055 VOID FmtClassUpdateNative(OBJECTREF *ppProtectedManagedData, BYTE *pNativeData, OBJECTREF *ppCleanupWorkListOnStack)
2056 {        
2057     CONTRACTL
2058     {
2059         THROWS;
2060         GC_TRIGGERS;
2061         MODE_COOPERATIVE;
2062         PRECONDITION(CheckPointer(ppProtectedManagedData));
2063     }
2064     CONTRACTL_END;
2065
2066     MethodTable *pMT = (*ppProtectedManagedData)->GetMethodTable();
2067     _ASSERTE(pMT->IsBlittable() || pMT->HasLayout());
2068     UINT32   cbsize = pMT->GetNativeSize();
2069
2070     if (pMT->IsBlittable())
2071     {
2072         memcpyNoGCRefs(pNativeData, (*ppProtectedManagedData)->GetData(), cbsize);
2073     }
2074     else
2075     {
2076         // This allows us to do a partial LayoutDestroyNative in the case of
2077         // a marshaling error on one of the fields.
2078         FillMemory(pNativeData, cbsize, 0);
2079         NativeLayoutDestroyer nld(pNativeData, pMT, cbsize);
2080         
2081         LayoutUpdateNative( (VOID**)ppProtectedManagedData,
2082                                 Object::GetOffsetOfFirstField(),
2083                                 pMT,
2084                                 pNativeData,
2085                                 ppCleanupWorkListOnStack);
2086         
2087         nld.SuppressRelease();
2088     }
2089
2090 }
2091
2092
2093 VOID FmtClassUpdateCLR(OBJECTREF *ppProtectedManagedData, BYTE *pNativeData)
2094 {       
2095     CONTRACTL
2096     {
2097         THROWS;
2098         GC_TRIGGERS;
2099         MODE_COOPERATIVE;
2100     }
2101     CONTRACTL_END;
2102     
2103     MethodTable *pMT = (*ppProtectedManagedData)->GetMethodTable();
2104     _ASSERTE(pMT->IsBlittable() || pMT->HasLayout());
2105     UINT32   cbsize = pMT->GetNativeSize();
2106
2107     if (pMT->IsBlittable())
2108     {
2109         memcpyNoGCRefs((*ppProtectedManagedData)->GetData(), pNativeData, cbsize);
2110     }
2111     else
2112     {
2113         LayoutUpdateCLR((VOID**)ppProtectedManagedData,
2114                             Object::GetOffsetOfFirstField(),
2115                             pMT,
2116                             (BYTE*)pNativeData
2117                            );
2118     }
2119 }
2120
2121
2122
2123 //=======================================================================
2124 // For each reference-typed FieldMarshaler field, marshals the current CLR value
2125 // to a new CLR instance and stores it in the GC portion of the FieldMarshaler.
2126 //
2127 // If fDeleteNativeCopies is true, it will also destroy the native version.
2128 //
2129 // NOTE: To avoid error-path leaks, this function attempts to destroy
2130 // all of the native fields even if one or more of the conversions fail.
2131 //=======================================================================
2132 VOID LayoutUpdateCLR(LPVOID *ppProtectedManagedData, SIZE_T offsetbias, MethodTable *pMT, BYTE *pNativeData)
2133 {
2134     CONTRACTL
2135     {
2136         THROWS;
2137         GC_TRIGGERS;
2138         MODE_COOPERATIVE;
2139         PRECONDITION(CheckPointer(pMT));
2140     }
2141     CONTRACTL_END;
2142
2143     // Don't try to destroy/free native the structure on exception, we may not own it. If we do own it and
2144     // are supposed to destroy/free it, we do it upstack (e.g. in a helper called from the marshaling stub).
2145
2146     FieldMarshaler* pFM = pMT->GetLayoutInfo()->GetFieldMarshalers();
2147     UINT  numReferenceFields = pMT->GetLayoutInfo()->GetNumCTMFields();
2148
2149     struct _gc
2150     {
2151         OBJECTREF pCLRValue;
2152         OBJECTREF pOldCLRValue;
2153     } gc;
2154
2155     gc.pCLRValue = NULL;
2156     gc.pOldCLRValue = NULL;
2157     LPVOID scalar = NULL;
2158
2159     GCPROTECT_BEGIN(gc)
2160     GCPROTECT_BEGININTERIOR(scalar)
2161     {
2162         g_IBCLogger.LogFieldMarshalersReadAccess(pMT);
2163
2164         while (numReferenceFields--)
2165         {
2166             pFM->Restore();
2167
2168             DWORD internalOffset = pFM->GetFieldDesc()->GetOffset();
2169
2170             if (pFM->IsScalarMarshaler())
2171             {
2172                 scalar = (LPVOID)(internalOffset + offsetbias + (BYTE*)(*ppProtectedManagedData));
2173                 // Note this will throw for FieldMarshaler_Illegal
2174                 pFM->ScalarUpdateCLR( pNativeData + pFM->GetExternalOffset(), scalar);
2175             }
2176             else if (pFM->IsNestedValueClassMarshaler())
2177             {
2178                 pFM->NestedValueClassUpdateCLR(pNativeData + pFM->GetExternalOffset(), ppProtectedManagedData, internalOffset + offsetbias);
2179             }
2180             else
2181             {
2182                 gc.pOldCLRValue = *(OBJECTREF*)(internalOffset + offsetbias + (BYTE*)(*ppProtectedManagedData));
2183                 pFM->UpdateCLR( pNativeData + pFM->GetExternalOffset(), &gc.pCLRValue, &gc.pOldCLRValue );
2184                 SetObjectReferenceUnchecked( (OBJECTREF*) (internalOffset + offsetbias + (BYTE*)(*ppProtectedManagedData)), gc.pCLRValue );
2185             }
2186
2187             ((BYTE*&)pFM) += MAXFIELDMARSHALERSIZE;
2188         }
2189     }
2190     GCPROTECT_END();
2191     GCPROTECT_END();
2192 }
2193
2194
2195 VOID LayoutDestroyNative(LPVOID pNative, MethodTable *pMT)
2196 {
2197     CONTRACTL
2198     {
2199         NOTHROW;
2200         GC_TRIGGERS;
2201         MODE_ANY;
2202         PRECONDITION(CheckPointer(pMT));
2203     }
2204     CONTRACTL_END;
2205     
2206     FieldMarshaler *pFM                   = pMT->GetLayoutInfo()->GetFieldMarshalers();
2207     UINT  numReferenceFields              = pMT->GetLayoutInfo()->GetNumCTMFields();
2208     BYTE *pNativeData                     = (BYTE*)pNative;
2209
2210     while (numReferenceFields--)
2211     {
2212         pFM->DestroyNative( pNativeData + pFM->GetExternalOffset() );
2213         ((BYTE*&)pFM) += MAXFIELDMARSHALERSIZE;
2214     }
2215 }
2216
2217 VOID FmtClassDestroyNative(LPVOID pNative, MethodTable *pMT)
2218 {       
2219     CONTRACTL
2220     {
2221         NOTHROW;
2222         GC_TRIGGERS;
2223         MODE_ANY;
2224         PRECONDITION(CheckPointer(pMT));
2225     }
2226     CONTRACTL_END;
2227     
2228     if (pNative)
2229     {
2230         if (!(pMT->IsBlittable()))
2231         {
2232             _ASSERTE(pMT->HasLayout());
2233             LayoutDestroyNative(pNative, pMT);
2234         }
2235     }
2236 }
2237
2238 VOID FmtValueTypeUpdateNative(LPVOID pProtectedManagedData, MethodTable *pMT, BYTE *pNativeData, OBJECTREF *ppCleanupWorkListOnStack)
2239 {        
2240     CONTRACTL
2241     {
2242         THROWS;
2243         GC_TRIGGERS;
2244         MODE_COOPERATIVE;
2245         PRECONDITION(CheckPointer(pMT));
2246     }
2247     CONTRACTL_END;
2248     
2249     _ASSERTE(pMT->IsValueType() && (pMT->IsBlittable() || pMT->HasLayout()));
2250     UINT32   cbsize = pMT->GetNativeSize();
2251
2252     if (pMT->IsBlittable())
2253     {
2254         memcpyNoGCRefs(pNativeData, pProtectedManagedData, cbsize);
2255     }
2256     else
2257     {
2258         // This allows us to do a partial LayoutDestroyNative in the case of
2259         // a marshaling error on one of the fields.
2260         FillMemory(pNativeData, cbsize, 0);
2261         
2262         NativeLayoutDestroyer nld(pNativeData, pMT, cbsize);
2263         
2264         LayoutUpdateNative( (VOID**)pProtectedManagedData,
2265                                 0,
2266                                 pMT,
2267                                 pNativeData,
2268                                 ppCleanupWorkListOnStack);
2269         
2270         nld.SuppressRelease();
2271     }
2272 }
2273
2274 VOID FmtValueTypeUpdateCLR(LPVOID pProtectedManagedData, MethodTable *pMT, BYTE *pNativeData)
2275 {       
2276     CONTRACTL
2277     {
2278         THROWS;
2279         GC_TRIGGERS;
2280         MODE_COOPERATIVE;
2281         PRECONDITION(CheckPointer(pMT));
2282     }
2283     CONTRACTL_END;
2284
2285     _ASSERTE(pMT->IsValueType() && (pMT->IsBlittable() || pMT->HasLayout()));
2286     UINT32   cbsize = pMT->GetNativeSize();
2287
2288     if (pMT->IsBlittable())
2289     {
2290         memcpyNoGCRefs(pProtectedManagedData, pNativeData, cbsize);
2291     }
2292     else
2293     {
2294         LayoutUpdateCLR((VOID**)pProtectedManagedData,
2295                             0,
2296                             pMT,
2297                             (BYTE*)pNativeData);
2298     }
2299 }
2300
2301 //=======================================================================
2302 // BSTR <--> System.String
2303 // See FieldMarshaler for details.
2304 //=======================================================================
2305 VOID FieldMarshaler_BSTR::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const 
2306 {
2307     CONTRACTL
2308     {
2309         THROWS;
2310         GC_NOTRIGGER;
2311         MODE_COOPERATIVE;
2312         INJECT_FAULT(COMPlusThrowOM());
2313         PRECONDITION(CheckPointer(pNativeValue));
2314     }
2315     CONTRACTL_END;
2316
2317     STRINGREF pString;
2318     *((OBJECTREF*)&pString) = *pCLRValue;
2319     
2320     if (pString == NULL)
2321         MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
2322     else
2323     {
2324         BSTR pBSTR = SysAllocStringLen(pString->GetBuffer(), pString->GetStringLength());
2325         if (!pBSTR)
2326             COMPlusThrowOM();
2327
2328         MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, pBSTR);        
2329     }
2330 }
2331
2332
2333 //=======================================================================
2334 // BSTR <--> System.String
2335 // See FieldMarshaler for details.
2336 //=======================================================================
2337 VOID FieldMarshaler_BSTR::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const 
2338 {
2339     STATIC_CONTRACT_THROWS;
2340     STATIC_CONTRACT_GC_TRIGGERS;
2341     STATIC_CONTRACT_MODE_COOPERATIVE;
2342
2343     _ASSERTE(NULL != pNativeValue);
2344     _ASSERTE(NULL != ppProtectedCLRValue);
2345
2346     STRINGREF pString;
2347     BSTR pBSTR = (BSTR)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
2348     
2349     if (!pBSTR)
2350         pString = NULL;
2351     else
2352     {
2353         struct Param : CallOutFilterParam {
2354             int             length;
2355             BSTR            pBSTR;
2356         }; Param param;
2357
2358         param.OneShot = TRUE;
2359         param.length = 0;
2360         param.pBSTR = pBSTR;
2361
2362         PAL_TRY(Param *, pParam, &param)
2363         {
2364             pParam->length = SysStringLen(pParam->pBSTR);
2365         }
2366         PAL_EXCEPT_FILTER(CallOutFilter)
2367         {
2368             _ASSERTE(!"CallOutFilter returned EXECUTE_HANDLER.");
2369         }
2370         PAL_ENDTRY;
2371         
2372         pString = StringObject::NewString(pBSTR, param.length);
2373     }
2374
2375     *((STRINGREF*)ppProtectedCLRValue) = pString;
2376 }
2377
2378
2379 //=======================================================================
2380 // BSTR <--> System.String
2381 // See FieldMarshaler for details.
2382 //=======================================================================
2383 VOID FieldMarshaler_BSTR::DestroyNativeImpl(LPVOID pNativeValue) const 
2384 {
2385     CONTRACTL
2386     {
2387         NOTHROW;
2388         GC_NOTRIGGER;
2389         MODE_ANY;
2390         PRECONDITION(CheckPointer(pNativeValue));
2391     }
2392     CONTRACTL_END;
2393
2394     BSTR pBSTR = (BSTR)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
2395     MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
2396     
2397     if (pBSTR)
2398     {
2399         // BSTR has been created, Delay load will not fail.
2400         CONTRACT_VIOLATION(ThrowsViolation);
2401         SysFreeString(pBSTR);
2402     }
2403 }
2404
2405 #ifdef FEATURE_COMINTEROP
2406 //===========================================================================================
2407 // Windows.Foundation.IReference'1<-- System.Nullable'1
2408 //
2409 VOID FieldMarshaler_Nullable::ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
2410 {
2411     CONTRACTL
2412     {
2413         THROWS;
2414         GC_TRIGGERS;
2415         MODE_COOPERATIVE;
2416         INJECT_FAULT(COMPlusThrowOM());
2417         PRECONDITION(CheckPointer(pNative));
2418         PRECONDITION(CheckPointer(pCLR));
2419     }
2420     CONTRACTL_END;
2421
2422     IUnknown *pUnk = NULL;
2423
2424     // ConvertToNative<T>(ref Nullable<T> pManaged) where T : struct
2425     MethodDescCallSite convertToNative(GetMethodDescForGenericInstantiation(MscorlibBinder::GetMethod(METHOD__NULLABLEMARSHALER__CONVERT_TO_NATIVE)));
2426     ARG_SLOT args[] =
2427     {
2428         PtrToArgSlot(pCLR)
2429     };
2430
2431     pUnk = (IUnknown*) convertToNative.Call_RetLPVOID(args);
2432
2433     MAYBE_UNALIGNED_WRITE(pNative, _PTR, pUnk);
2434 }
2435
2436 //===========================================================================================
2437 // Windows.Foundation.IReference'1--> System.Nullable'1
2438 //
2439 VOID FieldMarshaler_Nullable::ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
2440 {
2441     CONTRACTL
2442     {
2443         THROWS;
2444         GC_TRIGGERS;
2445         MODE_COOPERATIVE;
2446         PRECONDITION(CheckPointer(pNative));
2447         PRECONDITION(CheckPointer(pCLR));
2448     }
2449     CONTRACTL_END;
2450
2451     IUnknown *pUnk = (IUnknown*)MAYBE_UNALIGNED_READ(pNative, _PTR);
2452
2453     MethodDescCallSite convertToManaged(GetMethodDescForGenericInstantiation(MscorlibBinder::GetMethod(METHOD__NULLABLEMARSHALER__CONVERT_TO_MANAGED_RET_VOID)));
2454
2455     ARG_SLOT args[] =
2456     {
2457         PtrToArgSlot(pUnk),
2458         PtrToArgSlot(pCLR)
2459     };
2460
2461     //ConvertToManaged<T>(Intptr pNative, ref Nullable<T> retObj) where T : struct;
2462     convertToManaged.Call(args);
2463 }
2464
2465 //===========================================================================================
2466 // Windows.Foundation.IReference'1<--> System.Nullable'1
2467 //
2468 VOID FieldMarshaler_Nullable::DestroyNativeImpl(const VOID* pNative) const
2469
2470     CONTRACTL
2471     {
2472         NOTHROW;
2473         GC_TRIGGERS;
2474         MODE_ANY;
2475         PRECONDITION(CheckPointer(pNative));
2476     }
2477     CONTRACTL_END;
2478
2479     IUnknown *pUnk = (IUnknown*)MAYBE_UNALIGNED_READ(pNative, _PTR);
2480     MAYBE_UNALIGNED_WRITE(pNative, _PTR, NULL);
2481
2482     if (pUnk != NULL)
2483     {
2484         ULONG cbRef = SafeRelease(pUnk);
2485         LogInteropRelease(pUnk, cbRef, "Field marshaler destroy native");
2486     }
2487 }
2488
2489 //=======================================================================
2490 // HSTRING <--> System.String
2491 // See FieldMarshaler for details.
2492 //=======================================================================
2493 VOID FieldMarshaler_HSTRING::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const
2494 {
2495     CONTRACTL
2496     {
2497         THROWS;
2498         GC_TRIGGERS;
2499         MODE_COOPERATIVE;
2500         PRECONDITION(CheckPointer(pCLRValue));
2501         PRECONDITION(CheckPointer(pNativeValue));
2502     }
2503     CONTRACTL_END;
2504
2505     if (!WinRTSupported())
2506     {
2507         COMPlusThrow(kPlatformNotSupportedException, W("PlatformNotSupported_WinRT"));
2508     }
2509
2510     STRINGREF stringref = (STRINGREF)(*pCLRValue);
2511
2512     if (stringref == NULL)
2513     {
2514         DefineFullyQualifiedNameForClassW();
2515         StackSString ssFieldName(SString::Utf8, GetFieldDesc()->GetName());
2516
2517         SString errorString;
2518         errorString.LoadResource(CCompRC::Error, IDS_EE_BADMARSHALFIELD_NULL_HSTRING);
2519
2520         COMPlusThrow(kMarshalDirectiveException,
2521                      IDS_EE_BADMARSHALFIELD_ERROR_MSG,
2522                      GetFullyQualifiedNameForClassW(GetFieldDesc()->GetEnclosingMethodTable()),
2523                      ssFieldName.GetUnicode(),
2524                      errorString.GetUnicode());
2525     }
2526
2527     HSTRING hstring;
2528     IfFailThrow(WindowsCreateString(stringref->GetBuffer(), stringref->GetStringLength(), &hstring));
2529
2530     MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, hstring);
2531 }
2532
2533 //=======================================================================
2534 // HSTRING <--> System.String
2535 // See FieldMarshaler for details.
2536 //=======================================================================
2537 VOID FieldMarshaler_HSTRING::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const
2538 {
2539     CONTRACTL
2540     {
2541         THROWS;
2542         GC_TRIGGERS;
2543         MODE_COOPERATIVE;
2544         PRECONDITION(CheckPointer(pNativeValue));
2545         PRECONDITION(CheckPointer(ppProtectedCLRValue));
2546     }
2547     CONTRACTL_END;
2548
2549     if (!WinRTSupported())
2550     {
2551         COMPlusThrow(kPlatformNotSupportedException, W("PlatformNotSupported_WinRT"));
2552     }
2553
2554     // NULL HSTRINGS are equivilent to empty strings
2555     UINT32 cchString = 0;
2556     LPCWSTR pwszString = W("");
2557
2558     HSTRING hstring = (HSTRING)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
2559     if (hstring != NULL)
2560     {
2561         pwszString = WindowsGetStringRawBuffer(hstring, &cchString);
2562     }
2563
2564     STRINGREF stringref = StringObject::NewString(pwszString, cchString);
2565     *((STRINGREF *)ppProtectedCLRValue) = stringref;
2566 }
2567
2568 //=======================================================================
2569 // HSTRING <--> System.String
2570 // See FieldMarshaler for details.
2571 //=======================================================================
2572 VOID FieldMarshaler_HSTRING::DestroyNativeImpl(LPVOID pNativeValue) const
2573 {
2574     CONTRACTL
2575     {
2576         NOTHROW;
2577         GC_NOTRIGGER;
2578         MODE_ANY;
2579         PRECONDITION(CheckPointer(pNativeValue));
2580     }
2581     CONTRACTL_END;
2582
2583     HSTRING hstring = (HSTRING)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
2584     MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
2585
2586     if (hstring != NULL)
2587     {
2588         // We need this for code:System.Runtime.InteropServices.Marshal.DestroyStructure (user can explicitly call it)
2589         if (WinRTSupported())
2590         {
2591             // If WinRT is supported we've already loaded combase.dll, which means
2592             // this delay load will succeed
2593             CONTRACT_VIOLATION(ThrowsViolation);
2594             WindowsDeleteString(hstring);
2595         }
2596     }
2597 }
2598
2599 //=======================================================================================
2600 // Windows.UI.Xaml.Interop.TypeName <--> System.Type
2601 // 
2602 VOID FieldMarshaler_SystemType::UpdateNativeImpl(OBJECTREF * pCLRValue, LPVOID pNativeValue, OBJECTREF * ppCleanupWorkListOnStack) const
2603 {
2604     CONTRACTL
2605     {
2606         THROWS;
2607         GC_TRIGGERS;
2608         MODE_COOPERATIVE;
2609         PRECONDITION(CheckPointer(pCLRValue));
2610         PRECONDITION(CheckPointer(pNativeValue));
2611     }
2612     CONTRACTL_END;
2613     
2614     // ConvertToNative(System.Type managedType, TypeName *pTypeName)
2615     MethodDescCallSite convertToNative(METHOD__SYSTEMTYPEMARSHALER__CONVERT_TO_NATIVE);
2616     ARG_SLOT args[] =
2617     {
2618         ObjToArgSlot(*pCLRValue),
2619         PtrToArgSlot(pNativeValue)
2620     };
2621     convertToNative.Call(args);
2622 }
2623
2624 //=======================================================================================
2625 // Windows.UI.Xaml.Interop.TypeName <--> System.Type
2626 // 
2627 VOID FieldMarshaler_SystemType::UpdateCLRImpl(const VOID * pNativeValue, OBJECTREF * ppProtectedCLRValue, OBJECTREF * ppProtectedOldCLRValue) const
2628 {
2629     CONTRACTL
2630     {
2631         THROWS;
2632         GC_TRIGGERS;
2633         MODE_COOPERATIVE;
2634         PRECONDITION(CheckPointer(pNativeValue));
2635         PRECONDITION(CheckPointer(ppProtectedCLRValue));
2636     }
2637     CONTRACTL_END;
2638     
2639     // ConvertToManaged(TypeName *pTypeName, out System.Type)
2640     MethodDescCallSite convertToManaged(METHOD__SYSTEMTYPEMARSHALER__CONVERT_TO_MANAGED);
2641     ARG_SLOT args[] =
2642     {
2643         PtrToArgSlot(pNativeValue),
2644         PtrToArgSlot(ppProtectedCLRValue)
2645     };
2646     
2647     convertToManaged.Call(args);
2648 }
2649
2650 //=======================================================================================
2651 // Windows.UI.Xaml.Interop.TypeName <--> System.Type
2652 // Clear the HSTRING field
2653 // 
2654 VOID FieldMarshaler_SystemType::DestroyNativeImpl(LPVOID pNativeValue) const
2655 {
2656     CONTRACTL
2657     {
2658         NOTHROW;
2659         GC_NOTRIGGER;
2660         MODE_ANY;
2661         PRECONDITION(CheckPointer(pNativeValue));
2662         PRECONDITION(WinRTSupported());
2663     }
2664     CONTRACTL_END;
2665
2666     //
2667     // Call WindowsDeleteString instead of SystemTypeMarshaler.ClearNative
2668     // because WindowsDeleteString does not throw and is much faster
2669     //    
2670     size_t offset = offsetof(TypeNameNative, typeName);
2671     HSTRING hstring = (HSTRING)MAYBE_UNALIGNED_READ((LPBYTE) pNativeValue + offset , _PTR);
2672     MAYBE_UNALIGNED_WRITE((LPBYTE) pNativeValue + offset, _PTR, NULL);
2673     
2674     if (hstring != NULL)
2675     {
2676         // Note: we've already loaded combase.dll, which means this delay load will succeed
2677         CONTRACT_VIOLATION(ThrowsViolation);
2678         WindowsDeleteString(hstring);
2679     }
2680 }
2681
2682 //=======================================================================================
2683 // Windows.Foundation.HResult <--> System.Exception
2684 // Note: The WinRT struct has exactly 1 field, Value (an HRESULT)
2685 // 
2686 VOID FieldMarshaler_Exception::UpdateNativeImpl(OBJECTREF * pCLRValue, LPVOID pNativeValue, OBJECTREF * ppCleanupWorkListOnStack) const
2687 {
2688     CONTRACTL
2689     {
2690         THROWS;
2691         GC_TRIGGERS;
2692         MODE_COOPERATIVE;
2693         PRECONDITION(CheckPointer(pCLRValue));
2694         PRECONDITION(CheckPointer(pNativeValue));
2695     }
2696     CONTRACTL_END;
2697     
2698     // int ConvertToNative(Exception ex)
2699     MethodDescCallSite convertToNative(METHOD__HRESULTEXCEPTIONMARSHALER__CONVERT_TO_NATIVE);
2700     ARG_SLOT args[] =
2701     {
2702         ObjToArgSlot(*pCLRValue)
2703     };
2704     int iReturnedValue = convertToNative.Call_RetI4(args);
2705     MAYBE_UNALIGNED_WRITE(pNativeValue, 32, iReturnedValue);
2706 }
2707
2708 //=======================================================================================
2709 // Windows.Foundation.HResult <--> System.Exception
2710 // Note: The WinRT struct has exactly 1 field, Value (an HRESULT)
2711 // 
2712 VOID FieldMarshaler_Exception::UpdateCLRImpl(const VOID * pNativeValue, OBJECTREF * ppProtectedCLRValue, OBJECTREF * ppProtectedOldCLRValue) const
2713 {
2714     CONTRACTL
2715     {
2716         THROWS;
2717         GC_TRIGGERS;
2718         MODE_COOPERATIVE;
2719         PRECONDITION(CheckPointer(pNativeValue));
2720         PRECONDITION(CheckPointer(ppProtectedCLRValue));
2721     }
2722     CONTRACTL_END;
2723     
2724     // Exception ConvertToManaged(int hr)
2725     MethodDescCallSite convertToManaged(METHOD__HRESULTEXCEPTIONMARSHALER__CONVERT_TO_MANAGED);
2726     ARG_SLOT args[] =
2727     {
2728         (ARG_SLOT)MAYBE_UNALIGNED_READ(pNativeValue, 32)
2729     };
2730     *ppProtectedCLRValue = convertToManaged.Call_RetOBJECTREF(args);
2731 }
2732
2733 #endif // FEATURE_COMINTEROP
2734
2735
2736 //=======================================================================
2737 // Nested structure conversion
2738 // See FieldMarshaler for details.
2739 //=======================================================================
2740 VOID FieldMarshaler_NestedLayoutClass::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const 
2741 {
2742     CONTRACTL
2743     {
2744         THROWS;
2745         GC_TRIGGERS;
2746         MODE_COOPERATIVE;
2747         INJECT_FAULT(COMPlusThrowOM());
2748         PRECONDITION(CheckPointer(pNativeValue));
2749     }
2750     CONTRACTL_END;
2751
2752     UINT32 cbNativeSize = GetMethodTable()->GetNativeSize();
2753
2754     if (*pCLRValue == NULL)
2755     {
2756         ZeroMemoryInGCHeap(pNativeValue, cbNativeSize);
2757     }
2758     else
2759     {
2760         LayoutUpdateNative((LPVOID*)pCLRValue, Object::GetOffsetOfFirstField(), 
2761                            GetMethodTable(), (BYTE*)pNativeValue, ppCleanupWorkListOnStack);
2762     }
2763
2764 }
2765
2766
2767 //=======================================================================
2768 // Nested structure conversion
2769 // See FieldMarshaler for details.
2770 //=======================================================================
2771 VOID FieldMarshaler_NestedLayoutClass::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const 
2772 {
2773     CONTRACTL
2774     {
2775         THROWS;
2776         GC_TRIGGERS;
2777         MODE_COOPERATIVE;
2778         INJECT_FAULT(COMPlusThrowOM());
2779         PRECONDITION(CheckPointer(pNativeValue));
2780         PRECONDITION(CheckPointer(ppProtectedCLRValue));
2781     }
2782     CONTRACTL_END;
2783
2784     *ppProtectedCLRValue = GetMethodTable()->Allocate();
2785
2786     LayoutUpdateCLR( (LPVOID*)ppProtectedCLRValue,
2787                          Object::GetOffsetOfFirstField(),
2788                          GetMethodTable(),
2789                          (BYTE *)pNativeValue);
2790
2791 }
2792
2793
2794 //=======================================================================
2795 // Nested structure conversion
2796 // See FieldMarshaler for details.
2797 //=======================================================================
2798 VOID FieldMarshaler_NestedLayoutClass::DestroyNativeImpl(LPVOID pNativeValue) const 
2799 {
2800     CONTRACTL
2801     {
2802         NOTHROW;
2803         GC_TRIGGERS;
2804         MODE_ANY;
2805         PRECONDITION(CheckPointer(pNativeValue));
2806     }
2807     CONTRACTL_END;
2808
2809     LayoutDestroyNative(pNativeValue, GetMethodTable());
2810 }
2811
2812 #endif // CROSSGEN_COMPILE
2813
2814
2815 //=======================================================================
2816 // Nested structure conversion
2817 // See FieldMarshaler for details.
2818 //=======================================================================
2819 UINT32 FieldMarshaler_NestedLayoutClass::NativeSizeImpl() const
2820 {
2821     CONTRACTL
2822     {
2823         NOTHROW;
2824         GC_NOTRIGGER;
2825         MODE_ANY;
2826     }
2827     CONTRACTL_END;
2828
2829     return GetMethodTable()->GetLayoutInfo()->GetNativeSize();
2830 }
2831
2832 //=======================================================================
2833 // Nested structure conversion
2834 // See FieldMarshaler for details.
2835 //=======================================================================
2836 UINT32 FieldMarshaler_NestedLayoutClass::AlignmentRequirementImpl() const
2837 {
2838     CONTRACTL
2839     {
2840         THROWS;
2841         GC_TRIGGERS;
2842         MODE_ANY;
2843     }
2844     CONTRACTL_END;
2845
2846     return GetMethodTable()->GetLayoutInfo()->GetLargestAlignmentRequirementOfAllMembers();
2847 }
2848
2849 #if FEATURE_COMINTEROP
2850 MethodDesc* FieldMarshaler_Nullable::GetMethodDescForGenericInstantiation(MethodDesc* pMD) const
2851 {
2852     MethodDesc *pMethodInstantiation;
2853
2854     pMethodInstantiation = MethodDesc::FindOrCreateAssociatedMethodDesc(
2855         pMD,
2856         pMD->GetMethodTable(),
2857         FALSE,
2858         GetMethodTable()->GetInstantiation(),
2859         FALSE,
2860         TRUE);
2861
2862     _ASSERTE(pMethodInstantiation != NULL);
2863
2864     return pMethodInstantiation;
2865 }
2866 #endif //FEATURE_COMINTEROP
2867
2868 #ifndef CROSSGEN_COMPILE
2869
2870 //=======================================================================
2871 // Nested structure conversion
2872 // See FieldMarshaler for details.
2873 //=======================================================================
2874 VOID FieldMarshaler_NestedValueClass::NestedValueClassUpdateNativeImpl(const VOID **ppProtectedCLR, SIZE_T startoffset, LPVOID pNative, OBJECTREF *ppCleanupWorkListOnStack) const
2875 {
2876     CONTRACTL
2877     {
2878         THROWS;
2879         GC_TRIGGERS;
2880         MODE_COOPERATIVE;
2881         INJECT_FAULT(COMPlusThrowOM());
2882         PRECONDITION(CheckPointer(ppProtectedCLR));
2883         PRECONDITION(CheckPointer(pNative));
2884     }
2885     CONTRACTL_END;
2886
2887     MethodTable* pMT = GetMethodTable();
2888
2889     // would be better to detect this at class load time (that have a nested value
2890     // class with no layout) but don't have a way to know
2891     if (!pMT->GetLayoutInfo())
2892         COMPlusThrow(kArgumentException, IDS_NOLAYOUT_IN_EMBEDDED_VALUECLASS);
2893
2894     if (pMT->IsBlittable())
2895     {
2896         memcpyNoGCRefs(pNative, (BYTE*)(*ppProtectedCLR) + startoffset, pMT->GetNativeSize());
2897     }
2898     else
2899     {
2900 #ifdef _DEBUG
2901         _ASSERTE_MSG(!IsFixedBuffer(), "Cannot correctly marshal fixed buffers of non-blittable types");
2902 #endif
2903         LayoutUpdateNative((LPVOID*)ppProtectedCLR, startoffset, pMT, (BYTE*)pNative, ppCleanupWorkListOnStack);
2904     }
2905 }
2906
2907
2908 //=======================================================================
2909 // Nested structure conversion
2910 // See FieldMarshaler for details.
2911 //=======================================================================
2912 VOID FieldMarshaler_NestedValueClass::NestedValueClassUpdateCLRImpl(const VOID *pNative, LPVOID *ppProtectedCLR, SIZE_T startoffset) const
2913 {
2914     CONTRACTL
2915     {
2916         THROWS;
2917         GC_TRIGGERS;
2918         MODE_COOPERATIVE;
2919         PRECONDITION(CheckPointer(pNative));
2920         PRECONDITION(CheckPointer(ppProtectedCLR));
2921     }
2922     CONTRACTL_END;
2923
2924     MethodTable* pMT = GetMethodTable();
2925
2926     // would be better to detect this at class load time (that have a nested value
2927     // class with no layout) but don't have a way to know
2928     if (!pMT->GetLayoutInfo())
2929         COMPlusThrow(kArgumentException, IDS_NOLAYOUT_IN_EMBEDDED_VALUECLASS);
2930
2931     if (pMT->IsBlittable())
2932     {
2933         memcpyNoGCRefs((BYTE*)(*ppProtectedCLR) + startoffset, pNative, pMT->GetNativeSize());
2934     }
2935     else
2936     {
2937 #ifdef _DEBUG
2938         _ASSERTE_MSG(!IsFixedBuffer(), "Cannot correctly marshal fixed buffers of non-blittable types");
2939 #endif
2940         LayoutUpdateCLR((LPVOID*)ppProtectedCLR,
2941             startoffset,
2942             pMT,
2943             (BYTE *)pNative);
2944     }
2945 }
2946
2947
2948 //=======================================================================
2949 // Nested structure conversion
2950 // See FieldMarshaler for details.
2951 //=======================================================================
2952 VOID FieldMarshaler_NestedValueClass::DestroyNativeImpl(LPVOID pNativeValue) const 
2953 {
2954     CONTRACTL
2955     {
2956         NOTHROW;
2957         GC_TRIGGERS;
2958         MODE_ANY;
2959         PRECONDITION(CheckPointer(pNativeValue));
2960     }
2961     CONTRACTL_END;
2962
2963     MethodTable* pMT = GetMethodTable();
2964
2965     if (!pMT->IsBlittable())
2966     {
2967         LayoutDestroyNative(pNativeValue, pMT);
2968     }
2969 }
2970
2971 #endif // CROSSGEN_COMPILE
2972
2973
2974 //=======================================================================
2975 // Nested structure conversion
2976 // See FieldMarshaler for details.
2977 //=======================================================================
2978 UINT32 FieldMarshaler_NestedValueClass::NativeSizeImpl() const
2979 {
2980     CONTRACTL
2981     {
2982         NOTHROW;
2983         GC_NOTRIGGER;
2984         MODE_ANY;
2985     }
2986     CONTRACTL_END;
2987
2988     // this can't be marshalled as native type if no layout, so we allow the 
2989     // native size info to be created if available, but the size will only
2990     // be valid for native, not unions. Marshaller will throw exception if
2991     // try to marshall a value class with no layout
2992     if (GetMethodTable()->HasLayout())
2993         return GetMethodTable()->GetLayoutInfo()->GetNativeSize();
2994     
2995     return 0;
2996 }
2997
2998
2999 //=======================================================================
3000 // Nested structure conversion
3001 // See FieldMarshaler for details.
3002 //=======================================================================
3003 UINT32 FieldMarshaler_NestedValueClass::AlignmentRequirementImpl() const
3004 {
3005     CONTRACTL
3006     {
3007         THROWS;
3008         GC_TRIGGERS;
3009         MODE_ANY;
3010     }
3011     CONTRACTL_END;
3012     
3013     // this can't be marshalled as native type if no layout, so we allow the 
3014     // native size info to be created if available, but the alignment will only
3015     // be valid for native, not unions. Marshaller will throw exception if
3016     // try to marshall a value class with no layout
3017     if (GetMethodTable()->HasLayout())
3018     {
3019         UINT32  uAlignmentReq = GetMethodTable()->GetLayoutInfo()->GetLargestAlignmentRequirementOfAllMembers();
3020         return uAlignmentReq;
3021     }
3022     return 1;
3023 }
3024
3025
3026 #ifndef CROSSGEN_COMPILE
3027
3028 //=======================================================================
3029 // CoTask Uni <--> System.String
3030 // See FieldMarshaler for details.
3031 //=======================================================================
3032 VOID FieldMarshaler_StringUni::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const 
3033 {
3034     CONTRACTL
3035     {
3036         THROWS;
3037         GC_NOTRIGGER;
3038         MODE_COOPERATIVE;
3039         INJECT_FAULT(COMPlusThrowOM());
3040         PRECONDITION(CheckPointer(pNativeValue));
3041     }
3042     CONTRACTL_END;
3043
3044     STRINGREF pString;
3045     *((OBJECTREF*)&pString) = *pCLRValue;
3046     
3047     if (pString == NULL)
3048     {
3049         MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
3050     }
3051     else
3052     {
3053         DWORD nc = pString->GetStringLength();
3054         if (nc > MAX_SIZE_FOR_INTEROP)
3055             COMPlusThrow(kMarshalDirectiveException, IDS_EE_STRING_TOOLONG);
3056
3057         LPWSTR wsz = (LPWSTR)CoTaskMemAlloc( (nc + 1) * sizeof(WCHAR) );
3058         if (!wsz)
3059             COMPlusThrowOM();
3060
3061         memcpyNoGCRefs(wsz, pString->GetBuffer(), nc*sizeof(WCHAR));
3062         wsz[nc] = W('\0');
3063         MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, wsz);
3064     }
3065 }
3066
3067
3068 //=======================================================================
3069 // CoTask Uni <--> System.String
3070 // See FieldMarshaler for details.
3071 //=======================================================================
3072 VOID FieldMarshaler_StringUni::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const 
3073 {
3074     CONTRACTL
3075     {
3076         THROWS;
3077         GC_TRIGGERS;
3078         MODE_COOPERATIVE;
3079         PRECONDITION(CheckPointer(pNativeValue));
3080         PRECONDITION(CheckPointer(ppProtectedCLRValue));
3081     }
3082     CONTRACTL_END;
3083
3084     STRINGREF pString;
3085     LPCWSTR wsz = (LPCWSTR)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
3086     
3087     if (!wsz)
3088         pString = NULL;
3089     else
3090     {
3091         SIZE_T length = wcslen(wsz);
3092         if (length > MAX_SIZE_FOR_INTEROP)
3093             COMPlusThrow(kMarshalDirectiveException, IDS_EE_STRING_TOOLONG);
3094
3095         pString = StringObject::NewString(wsz, (DWORD)length);
3096     }
3097     
3098     *((STRINGREF*)ppProtectedCLRValue) = pString;
3099 }
3100
3101
3102 //=======================================================================
3103 // CoTask Uni <--> System.String
3104 // See FieldMarshaler for details.
3105 //=======================================================================
3106 VOID FieldMarshaler_StringUni::DestroyNativeImpl(LPVOID pNativeValue) const 
3107 {
3108     CONTRACTL
3109     {
3110         NOTHROW;
3111         GC_NOTRIGGER;
3112         MODE_ANY;
3113         PRECONDITION(CheckPointer(pNativeValue));        
3114     }
3115     CONTRACTL_END;
3116     
3117     LPWSTR wsz = (LPWSTR)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
3118     MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
3119     if (wsz)
3120         CoTaskMemFree(wsz);
3121 }
3122
3123
3124
3125 //=======================================================================
3126 // CoTask Ansi <--> System.String
3127 // See FieldMarshaler for details.
3128 //=======================================================================
3129 VOID FieldMarshaler_StringAnsi::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const 
3130 {
3131     CONTRACTL
3132     {
3133         THROWS;
3134         GC_TRIGGERS;
3135         MODE_COOPERATIVE;
3136         INJECT_FAULT(COMPlusThrowOM());
3137         PRECONDITION(CheckPointer(pNativeValue));
3138     }
3139     CONTRACTL_END;
3140
3141     STRINGREF pString;
3142     *((OBJECTREF*)&pString) = *pCLRValue;
3143     
3144     if (pString == NULL)
3145     {
3146         MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
3147     }
3148     else
3149     {
3150         DWORD nc = pString->GetStringLength();
3151         if (nc > MAX_SIZE_FOR_INTEROP)
3152             COMPlusThrow(kMarshalDirectiveException, IDS_EE_STRING_TOOLONG);
3153  
3154         LPSTR sz = (LPSTR)CoTaskMemAlloc( (nc + 1) * 2 /* 2 for MBCS */ );
3155         if (!sz)
3156             COMPlusThrowOM(); 
3157
3158         int nbytes = InternalWideToAnsi(pString->GetBuffer(),
3159                                         nc,
3160                                         sz,
3161                                         nc*2,
3162                                         m_BestFitMap,
3163                                         m_ThrowOnUnmappableChar);
3164         sz[nbytes] = '\0';
3165
3166         MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, sz);
3167      }
3168 }
3169
3170
3171 //=======================================================================
3172 // CoTask Ansi <--> System.String
3173 // See FieldMarshaler for details.
3174 //=======================================================================
3175 VOID FieldMarshaler_StringAnsi::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const 
3176 {
3177     CONTRACTL
3178     {
3179         THROWS;
3180         GC_TRIGGERS;
3181         MODE_COOPERATIVE;
3182         INJECT_FAULT(COMPlusThrowOM());
3183         PRECONDITION(CheckPointer(pNativeValue));
3184         PRECONDITION(CheckPointer(ppProtectedCLRValue));
3185     }
3186     CONTRACTL_END;
3187
3188     STRINGREF pString = NULL;
3189     LPCSTR sz = (LPCSTR)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
3190     if (!sz) 
3191         pString = NULL;
3192     else 
3193     {
3194         MAKE_WIDEPTR_FROMANSI(wsztemp, sz);
3195         pString = StringObject::NewString(wsztemp, __lwsztemp - 1);
3196     }
3197     
3198     *((STRINGREF*)ppProtectedCLRValue) = pString;
3199 }
3200
3201
3202 //=======================================================================
3203 // CoTask Ansi <--> System.String
3204 // See FieldMarshaler for details.
3205 //=======================================================================
3206 VOID FieldMarshaler_StringAnsi::DestroyNativeImpl(LPVOID pNativeValue) const 
3207 {
3208     CONTRACTL
3209     {
3210         NOTHROW;
3211         GC_NOTRIGGER;
3212         MODE_ANY;
3213         PRECONDITION(CheckPointer(pNativeValue));        
3214     }
3215     CONTRACTL_END;
3216     
3217     LPSTR sz = (LPSTR)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
3218     MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
3219     if (sz)
3220         CoTaskMemFree(sz);
3221 }
3222
3223 //=======================================================================
3224 // CoTask Utf8 <--> System.String
3225 // See FieldMarshaler for details.
3226 //=======================================================================
3227 VOID FieldMarshaler_StringUtf8::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const
3228 {
3229     CONTRACTL
3230     {
3231         THROWS;
3232         GC_TRIGGERS;
3233         MODE_COOPERATIVE;
3234         INJECT_FAULT(COMPlusThrowOM());
3235         PRECONDITION(CheckPointer(pNativeValue));
3236     }
3237     CONTRACTL_END;
3238
3239     STRINGREF pString = (STRINGREF)(*pCLRValue);
3240     if (pString == NULL)
3241     {
3242         MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
3243     }
3244     else
3245     {
3246         DWORD nc = pString->GetStringLength();
3247         if (nc > MAX_SIZE_FOR_INTEROP)
3248             COMPlusThrow(kMarshalDirectiveException, IDS_EE_STRING_TOOLONG);
3249
3250         // Characters would be # of characters + 1 in case left over high surrogate is ?
3251         // Max 3 bytes per char for basic multi-lingual plane.
3252         nc = (nc + 1) * MAX_UTF8_CHAR_SIZE;
3253         // +1 for '\0'
3254         LPUTF8  lpBuffer = (LPUTF8)CoTaskMemAlloc(nc + 1);
3255         if (!lpBuffer)
3256         {
3257             COMPlusThrowOM();
3258         }
3259
3260         // UTF8Marshaler.ConvertToNative
3261         MethodDescCallSite convertToNative(METHOD__CUTF8MARSHALER__CONVERT_TO_NATIVE);
3262         
3263         ARG_SLOT args[] =
3264         {
3265             ((ARG_SLOT)(CLR_I4)0),
3266             ObjToArgSlot(*pCLRValue),
3267             PtrToArgSlot(lpBuffer)
3268         };
3269         convertToNative.Call(args);
3270         MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, lpBuffer);
3271     }
3272 }
3273
3274
3275 //=======================================================================
3276 // CoTask Utf8 <--> System.String
3277 // See FieldMarshaler for details.
3278 //=======================================================================
3279 VOID FieldMarshaler_StringUtf8::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const
3280 {
3281     CONTRACTL
3282     {
3283         THROWS;
3284         GC_TRIGGERS;
3285         MODE_COOPERATIVE;
3286         INJECT_FAULT(COMPlusThrowOM());
3287         PRECONDITION(CheckPointer(pNativeValue));
3288         PRECONDITION(CheckPointer(ppProtectedCLRValue));
3289     }
3290     CONTRACTL_END;
3291
3292     STRINGREF pString = NULL;
3293     LPCUTF8  sz = (LPCUTF8)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
3294     if (sz)
3295     {
3296         MethodDescCallSite convertToManaged(METHOD__CUTF8MARSHALER__CONVERT_TO_MANAGED);
3297         ARG_SLOT args[] =
3298         {
3299             PtrToArgSlot(sz),
3300         };
3301         pString = convertToManaged.Call_RetSTRINGREF(args);
3302     }
3303     *((STRINGREF*)ppProtectedCLRValue) = pString;
3304 }
3305
3306 //=======================================================================
3307 // CoTask Utf8 <--> System.String
3308 // See FieldMarshaler for details.
3309 //=======================================================================
3310 VOID FieldMarshaler_StringUtf8::DestroyNativeImpl(LPVOID pNativeValue) const
3311 {
3312     CONTRACTL
3313     {
3314         NOTHROW;
3315         GC_NOTRIGGER;
3316         MODE_ANY;
3317         PRECONDITION(CheckPointer(pNativeValue));
3318     }
3319     CONTRACTL_END;
3320
3321     LPCUTF8 lpBuffer = (LPCUTF8)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
3322     MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
3323     if (lpBuffer)
3324         CoTaskMemFree((LPVOID)lpBuffer);
3325 }
3326
3327 //=======================================================================
3328 // FixedString <--> System.String
3329 // See FieldMarshaler for details.
3330 //=======================================================================
3331 VOID FieldMarshaler_FixedStringUni::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const 
3332 {
3333     CONTRACTL
3334     {
3335         NOTHROW;
3336         GC_NOTRIGGER;
3337         MODE_COOPERATIVE;
3338         PRECONDITION(CheckPointer(pNativeValue));
3339     }
3340     CONTRACTL_END;
3341
3342     STRINGREF pString;
3343     *((OBJECTREF*)&pString) = *pCLRValue;
3344     
3345     if (pString == NULL)
3346     {
3347         MAYBE_UNALIGNED_WRITE(pNativeValue, 16, W('\0'));
3348     }
3349     else
3350     {
3351         DWORD nc = pString->GetStringLength();
3352         if (nc >= m_numchar)
3353             nc = m_numchar - 1;
3354
3355         memcpyNoGCRefs(pNativeValue, pString->GetBuffer(), nc*sizeof(WCHAR));
3356         MAYBE_UNALIGNED_WRITE(&(((WCHAR*)pNativeValue)[nc]), 16, W('\0'));
3357     }
3358
3359 }
3360
3361
3362 //=======================================================================
3363 // FixedString <--> System.String
3364 // See FieldMarshaler for details.
3365 //=======================================================================
3366 VOID FieldMarshaler_FixedStringUni::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const 
3367 {
3368     CONTRACTL
3369     {
3370         THROWS;
3371         GC_TRIGGERS;
3372         MODE_COOPERATIVE;
3373         PRECONDITION(CheckPointer(pNativeValue));
3374         PRECONDITION(CheckPointer(ppProtectedCLRValue));
3375     }
3376     CONTRACTL_END;
3377
3378     STRINGREF pString;
3379     SIZE_T    ncActual = wcsnlen((const WCHAR *)pNativeValue, m_numchar);
3380
3381     if (!FitsIn<int>(ncActual))
3382         COMPlusThrowHR(COR_E_OVERFLOW);
3383
3384     pString = StringObject::NewString((const WCHAR *)pNativeValue, (int)ncActual);
3385     *((STRINGREF*)ppProtectedCLRValue) = pString;
3386 }
3387
3388
3389
3390
3391
3392
3393
3394 //=======================================================================
3395 // FixedString <--> System.String
3396 // See FieldMarshaler for details.
3397 //=======================================================================
3398 VOID FieldMarshaler_FixedStringAnsi::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const 
3399 {
3400     CONTRACTL
3401     {
3402         THROWS;
3403         GC_TRIGGERS;
3404         MODE_COOPERATIVE;
3405         PRECONDITION(CheckPointer(pNativeValue));
3406     }
3407     CONTRACTL_END;
3408
3409     STRINGREF pString;
3410     *((OBJECTREF*)&pString) = *pCLRValue;
3411     
3412     if (pString == NULL)
3413         *((CHAR*)pNativeValue) = W('\0');
3414     else
3415     {
3416         DWORD nc = pString->GetStringLength();
3417         if (nc >= m_numchar)
3418             nc = m_numchar - 1;
3419
3420         int cbwritten = InternalWideToAnsi(pString->GetBuffer(),
3421             nc,
3422             (CHAR*)pNativeValue,
3423             m_numchar,
3424             m_BestFitMap,
3425             m_ThrowOnUnmappableChar);
3426
3427         // Handle the case where SizeConst == Number of bytes.For single byte chars 
3428         // this will never be the case since nc >= m_numchar check will truncate the last 
3429         // character, but for multibyte chars nc>= m_numchar check won't truncate since GetStringLength
3430         // gives number of characters but not the actual number of bytes. For such cases need to make 
3431         // sure that we dont write one past the buffer.
3432         if (cbwritten == (int) m_numchar)
3433             --cbwritten;
3434
3435         ((CHAR*)pNativeValue)[cbwritten] = '\0';
3436     }
3437 }
3438
3439
3440 //=======================================================================
3441 // FixedString <--> System.String
3442 // See FieldMarshaler for details.
3443 //=======================================================================
3444 VOID FieldMarshaler_FixedStringAnsi::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const 
3445 {
3446     CONTRACTL
3447     {
3448         THROWS;
3449         GC_TRIGGERS;
3450         MODE_COOPERATIVE;
3451         INJECT_FAULT(COMPlusThrowOM());
3452         PRECONDITION(CheckPointer(pNativeValue));
3453         PRECONDITION(CheckPointer(ppProtectedCLRValue));
3454
3455         // should not have slipped past the metadata
3456         PRECONDITION(m_numchar != 0);
3457     }
3458     CONTRACTL_END;
3459
3460     STRINGREF pString;
3461     if (m_numchar == 0)
3462     {
3463         // but if it does, better to throw an exception tardily rather than
3464         // allow a memory corrupt.
3465         COMPlusThrow(kMarshalDirectiveException);
3466     }
3467
3468     UINT32 allocSize = m_numchar + 2;
3469     if (allocSize < m_numchar)
3470         ThrowOutOfMemory();
3471     
3472     LPSTR tempbuf = (LPSTR)(_alloca((size_t)allocSize));
3473     if (!tempbuf)
3474         ThrowOutOfMemory();
3475
3476     memcpyNoGCRefs(tempbuf, pNativeValue, m_numchar);
3477     tempbuf[m_numchar-1] = '\0';
3478     tempbuf[m_numchar] = '\0';
3479     tempbuf[m_numchar+1] = '\0';
3480
3481     allocSize = m_numchar * sizeof(WCHAR);
3482     if (allocSize < m_numchar)
3483         ThrowOutOfMemory();
3484     
3485     LPWSTR    wsztemp = (LPWSTR)_alloca( (size_t)allocSize );
3486     int ncwritten = MultiByteToWideChar(CP_ACP,
3487                                         MB_PRECOMPOSED,
3488                                         tempbuf,
3489                                         -1,  // # of CHAR's in inbuffer
3490                                         wsztemp,
3491                                         m_numchar                       // size (in WCHAR) of outbuffer
3492                                         );
3493
3494     if (!ncwritten)
3495     {
3496         // intentionally not throwing for MB2WC failure. We don't always know
3497         // whether to expect a valid string in the buffer and we don't want
3498         // to throw exceptions randomly.
3499         ncwritten++;
3500     }
3501
3502     pString = StringObject::NewString((const WCHAR *)wsztemp, ncwritten-1);
3503     *((STRINGREF*)ppProtectedCLRValue) = pString;
3504 }
3505
3506
3507 //=======================================================================
3508 // CHAR[] <--> char[]
3509 // See FieldMarshaler for details.
3510 //=======================================================================
3511 VOID FieldMarshaler_FixedCharArrayAnsi::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const 
3512 {
3513     CONTRACTL
3514     {
3515         THROWS;
3516         GC_TRIGGERS;
3517         MODE_COOPERATIVE;
3518         INJECT_FAULT(COMPlusThrowOM());
3519         PRECONDITION(CheckPointer(pNativeValue));
3520     }
3521     CONTRACTL_END;
3522
3523     I2ARRAYREF pArray;
3524     *((OBJECTREF*)&pArray) = *pCLRValue;
3525
3526     if (pArray == NULL)
3527         FillMemory(pNativeValue, m_numElems * sizeof(CHAR), 0);
3528     else
3529     {
3530         if (pArray->GetNumComponents() < m_numElems)
3531             COMPlusThrow(kArgumentException, IDS_WRONGSIZEARRAY_IN_NSTRUCT);
3532         else
3533         {
3534             InternalWideToAnsi((const WCHAR*) pArray->GetDataPtr(),
3535                                m_numElems,
3536                               (CHAR*)pNativeValue,
3537                                m_numElems * sizeof(CHAR),
3538                                m_BestFitMap,
3539                                m_ThrowOnUnmappableChar);
3540         }
3541     }
3542 }
3543
3544
3545 //=======================================================================
3546 // CHAR[] <--> char[]
3547 // See FieldMarshaler for details.
3548 //=======================================================================
3549 VOID FieldMarshaler_FixedCharArrayAnsi::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const 
3550 {
3551     CONTRACTL
3552     {
3553         THROWS;
3554         GC_TRIGGERS;
3555         MODE_COOPERATIVE;
3556         INJECT_FAULT(COMPlusThrowOM());
3557         PRECONDITION(CheckPointer(pNativeValue));
3558         PRECONDITION(CheckPointer(ppProtectedCLRValue));
3559     }
3560     CONTRACTL_END;
3561
3562     *ppProtectedCLRValue = AllocatePrimitiveArray(ELEMENT_TYPE_CHAR, m_numElems);
3563
3564     MultiByteToWideChar(CP_ACP,
3565                         MB_PRECOMPOSED,
3566                         (const CHAR *)pNativeValue,
3567                         m_numElems * sizeof(CHAR), // size, in bytes, of in buffer
3568                         (WCHAR*) ((*((I2ARRAYREF*)ppProtectedCLRValue))->GetDirectPointerToNonObjectElements()),
3569                         m_numElems);               // size, in WCHAR's of outbuffer                       
3570 }
3571
3572 #endif // CROSSGEN_COMPILE
3573
3574
3575 //=======================================================================
3576 // Embedded array
3577 // See FieldMarshaler for details.
3578 //=======================================================================
3579 FieldMarshaler_FixedArray::FieldMarshaler_FixedArray(IMDInternalImport *pMDImport, mdTypeDef cl, UINT32 numElems, VARTYPE vt, MethodTable* pElementMT)
3580 : m_numElems(numElems)
3581 , m_vt(vt)
3582 , m_BestFitMap(FALSE)
3583 , m_ThrowOnUnmappableChar(FALSE)
3584 {
3585     CONTRACTL
3586     {
3587         THROWS;
3588         GC_TRIGGERS;
3589         MODE_ANY;
3590         PRECONDITION(CheckPointer(pElementMT));
3591         PRECONDITION(vt != VTHACK_ANSICHAR);        // This must be handled by the FixedCharArrayAnsi marshaler.
3592     }
3593     CONTRACTL_END;
3594
3595     // Only attempt to read the best fit mapping attribute if required to minimize
3596     // custom attribute accesses.
3597     if (vt == VT_LPSTR || vt == VT_RECORD)
3598     {
3599         BOOL BestFitMap = FALSE;
3600         BOOL ThrowOnUnmappableChar = FALSE;
3601         ReadBestFitCustomAttribute(pMDImport, cl, &BestFitMap, &ThrowOnUnmappableChar);      
3602         m_BestFitMap = !!BestFitMap;
3603         m_ThrowOnUnmappableChar = !!ThrowOnUnmappableChar;
3604     }
3605
3606     m_arrayType.SetValue(ClassLoader::LoadArrayTypeThrowing(TypeHandle(pElementMT),
3607                                                      ELEMENT_TYPE_SZARRAY,
3608                                                      0,
3609                                                      ClassLoader::LoadTypes,
3610                                                      pElementMT->GetLoadLevel()));
3611 }
3612
3613
3614 #ifndef CROSSGEN_COMPILE
3615
3616 //=======================================================================
3617 // Embedded array
3618 // See FieldMarshaler for details.
3619 //=======================================================================
3620 VOID FieldMarshaler_FixedArray::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const 
3621 {
3622     CONTRACTL
3623     {
3624         THROWS;
3625         GC_TRIGGERS;
3626         MODE_COOPERATIVE;
3627         PRECONDITION(CheckPointer(pNativeValue));
3628     }
3629     CONTRACTL_END;
3630
3631     if (*pCLRValue == NULL)
3632     {
3633         FillMemory(pNativeValue, NativeSize(), 0);
3634     }
3635     else
3636     {
3637         // Make sure the size of the array is >= as specified in the MarshalAs attribute (via the SizeConst field).
3638         if ((*pCLRValue)->GetNumComponents() < m_numElems)
3639             COMPlusThrow(kArgumentException, IDS_WRONGSIZEARRAY_IN_NSTRUCT);
3640   
3641         // Marshal the contents from the managed array to the native array.
3642         const OleVariant::Marshaler *pMarshaler = OleVariant::GetMarshalerForVarType(m_vt, TRUE);  
3643         if (pMarshaler == NULL || pMarshaler->ComToOleArray == NULL)
3644         {
3645             memcpyNoGCRefs(pNativeValue, (*(BASEARRAYREF*)pCLRValue)->GetDataPtr(), NativeSize());
3646         }
3647         else
3648         {
3649             MethodTable *pElementMT = m_arrayType.GetValue().AsArray()->GetArrayElementTypeHandle().GetMethodTable();
3650
3651             // We never operate on an uninitialized native layout here, we have zero'ed it if needed.
3652             // Therefore fOleArrayIsValid is always TRUE.
3653             pMarshaler->ComToOleArray((BASEARRAYREF*)pCLRValue, pNativeValue, pElementMT, m_BestFitMap, m_ThrowOnUnmappableChar, TRUE, m_numElems);
3654         }
3655     }
3656 }
3657
3658
3659 //=======================================================================
3660 // Embedded array
3661 // See FieldMarshaler for details.
3662 //=======================================================================
3663 VOID FieldMarshaler_FixedArray::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const 
3664 {
3665     CONTRACTL
3666     {
3667         THROWS;
3668         GC_TRIGGERS;
3669         MODE_COOPERATIVE;
3670         INJECT_FAULT(COMPlusThrowOM());
3671         PRECONDITION(CheckPointer(pNativeValue));
3672         PRECONDITION(CheckPointer(ppProtectedCLRValue));
3673     }
3674     CONTRACTL_END;
3675
3676     // Allocate the value class array.
3677     *ppProtectedCLRValue = AllocateArrayEx(m_arrayType.GetValue(), (INT32*)&m_numElems, 1);
3678
3679     // Marshal the contents from the native array to the managed array.
3680     const OleVariant::Marshaler *pMarshaler = OleVariant::GetMarshalerForVarType(m_vt, TRUE);        
3681     if (pMarshaler == NULL || pMarshaler->OleToComArray == NULL)
3682     {
3683         memcpyNoGCRefs((*(BASEARRAYREF*)ppProtectedCLRValue)->GetDataPtr(), pNativeValue, NativeSize());
3684     }
3685     else
3686     {
3687         MethodTable *pElementMT = m_arrayType.GetValue().AsArray()->GetArrayElementTypeHandle().GetMethodTable();
3688         pMarshaler->OleToComArray((VOID *)pNativeValue, (BASEARRAYREF*)ppProtectedCLRValue, pElementMT);
3689     }
3690 }
3691
3692 //=======================================================================
3693 // Embedded array
3694 // See FieldMarshaler for details.
3695 //=======================================================================
3696 VOID FieldMarshaler_FixedArray::DestroyNativeImpl(LPVOID pNativeValue) const
3697 {
3698     CONTRACTL
3699     {
3700         NOTHROW;
3701         GC_TRIGGERS;
3702         MODE_ANY;
3703         INJECT_FAULT(COMPlusThrowOM());
3704         PRECONDITION(CheckPointer(pNativeValue));
3705     }
3706     CONTRACTL_END;
3707
3708     const OleVariant::Marshaler *pMarshaler = OleVariant::GetMarshalerForVarType(m_vt, FALSE);
3709
3710     if (pMarshaler != NULL && pMarshaler->ClearOleArray != NULL)
3711     {
3712         MethodTable *pElementMT = m_arrayType.GetValue().AsArray()->GetArrayElementTypeHandle().GetMethodTable();
3713         pMarshaler->ClearOleArray(pNativeValue, m_numElems, pElementMT);
3714     }
3715 }
3716
3717 #endif // CROSSGEN_COMPILE
3718
3719
3720 //=======================================================================
3721 // Embedded array
3722 // See FieldMarshaler for details.
3723 //=======================================================================
3724 UINT32 FieldMarshaler_FixedArray::AlignmentRequirementImpl() const
3725 {
3726     WRAPPER_NO_CONTRACT;
3727
3728     UINT32 alignment = 0;
3729     TypeHandle elementType = m_arrayType.GetValue().AsArray()->GetArrayElementTypeHandle();
3730
3731     switch (m_vt)
3732     {
3733         case VT_DECIMAL:
3734             alignment = 8;
3735             break;
3736
3737         case VT_VARIANT:
3738             alignment = 8;
3739             break;
3740
3741         case VT_RECORD:
3742             alignment = elementType.GetMethodTable()->GetLayoutInfo()->GetLargestAlignmentRequirementOfAllMembers();    
3743             break;
3744
3745         default:
3746             alignment = OleVariant::GetElementSizeForVarType(m_vt, elementType.GetMethodTable());
3747             break;
3748     }
3749
3750     return alignment;
3751 }
3752   
3753 #ifndef CROSSGEN_COMPILE
3754
3755 #ifdef FEATURE_CLASSIC_COMINTEROP
3756 //=======================================================================
3757 // SafeArray
3758 // See FieldMarshaler for details.
3759 //=======================================================================
3760 VOID FieldMarshaler_SafeArray::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const 
3761 {
3762     CONTRACTL
3763     {
3764         THROWS;
3765         GC_TRIGGERS;
3766         MODE_COOPERATIVE;
3767         PRECONDITION(CheckPointer(pNativeValue));
3768     }
3769     CONTRACTL_END;
3770
3771     BASEARRAYREF pArray;
3772     *((OBJECTREF*)&pArray) = *pCLRValue;
3773     if ((pArray == NULL) || (OBJECTREFToObject(pArray) == NULL))
3774     {
3775         FillMemory(pNativeValue, sizeof(LPSAFEARRAY*), 0);
3776         return;
3777     }
3778     
3779     LPSAFEARRAY* pSafeArray;
3780     pSafeArray = (LPSAFEARRAY*)pNativeValue;
3781
3782     VARTYPE vt = m_vt;
3783     MethodTable* pMT = m_pMT.GetValueMaybeNull();
3784
3785     GCPROTECT_BEGIN(pArray)
3786     {
3787         if (vt == VT_EMPTY)
3788             vt = OleVariant::GetElementVarTypeForArrayRef(pArray);
3789
3790         if (!pMT)
3791             pMT = OleVariant::GetArrayElementTypeWrapperAware(&pArray).GetMethodTable();
3792
3793         // OleVariant calls throw on error.
3794         *pSafeArray = OleVariant::CreateSafeArrayForArrayRef(&pArray, vt, pMT);
3795         OleVariant::MarshalSafeArrayForArrayRef(&pArray, *pSafeArray, vt, pMT);
3796     }
3797     GCPROTECT_END();
3798 }
3799
3800
3801 //=======================================================================
3802 // SafeArray
3803 // See FieldMarshaler for details.
3804 //=======================================================================
3805 VOID FieldMarshaler_SafeArray::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const 
3806 {
3807     CONTRACTL
3808     {
3809         THROWS;
3810         GC_TRIGGERS;
3811         MODE_COOPERATIVE;
3812         INJECT_FAULT(COMPlusThrowOM());
3813         PRECONDITION(CheckPointer(pNativeValue));
3814         PRECONDITION(CheckPointer(ppProtectedCLRValue));
3815     }
3816     CONTRACTL_END;
3817
3818     LPSAFEARRAY* pSafeArray;
3819     pSafeArray = (LPSAFEARRAY*)pNativeValue;
3820
3821     if ((pSafeArray == NULL) || (*pSafeArray == NULL))
3822     {
3823         *ppProtectedCLRValue = NULL;
3824         return;
3825     }
3826
3827     VARTYPE vt = m_vt;
3828     MethodTable* pMT = m_pMT.GetValueMaybeNull();
3829
3830     // If we have an empty vartype, get it from the safearray vartype
3831     if (vt == VT_EMPTY)
3832     {
3833         if (FAILED(ClrSafeArrayGetVartype(*pSafeArray, &vt)))
3834             COMPlusThrow(kArgumentException, IDS_EE_INVALID_SAFEARRAY);
3835     }
3836
3837     // Get the method table if we need to.
3838     if ((vt == VT_RECORD) && (!pMT))
3839         pMT = OleVariant::GetElementTypeForRecordSafeArray(*pSafeArray).GetMethodTable();
3840
3841     // If we have a single dimension safearray, it will be converted into a SZArray.
3842     // SZArray must have a lower bound of zero.
3843     LONG LowerBound = -1;
3844     UINT Dimensions = SafeArrayGetDim( (SAFEARRAY*)*pSafeArray );    
3845
3846     if (Dimensions == 1)
3847     {
3848         HRESULT hr = SafeArrayGetLBound((SAFEARRAY*)*pSafeArray, 1, &LowerBound);
3849         if ( FAILED(hr) || LowerBound != 0)
3850         COMPlusThrow(kSafeArrayRankMismatchException, IDS_EE_SAFEARRAYSZARRAYMISMATCH);
3851     }
3852     
3853     // OleVariant calls throw on error.
3854     *ppProtectedCLRValue = OleVariant::CreateArrayRefForSafeArray(*pSafeArray, vt, pMT);
3855     OleVariant::MarshalArrayRefForSafeArray(*pSafeArray, (BASEARRAYREF*)ppProtectedCLRValue, vt, pMT);
3856 }
3857
3858
3859 //=======================================================================
3860 // SafeArray
3861 // See FieldMarshaler for details.
3862 //=======================================================================
3863 VOID FieldMarshaler_SafeArray::DestroyNativeImpl(LPVOID pNativeValue) const 
3864 {
3865     CONTRACTL
3866     {
3867         NOTHROW;
3868         GC_TRIGGERS;
3869         MODE_ANY;
3870         PRECONDITION(CheckPointer(pNativeValue));
3871     }
3872     CONTRACTL_END;
3873
3874     HRESULT hr;
3875     GCX_PREEMP();
3876
3877     LPSAFEARRAY psa = (LPSAFEARRAY)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
3878     MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
3879     
3880     if (psa)
3881     {
3882         _ASSERTE (GetModuleHandleA("oleaut32.dll") != NULL);
3883         // SafeArray has been created, which means oleaut32 should have been loaded.
3884         // Delay load will not fail.
3885         CONTRACT_VIOLATION(ThrowsViolation);
3886         hr = SafeArrayDestroy(psa);
3887         _ASSERTE(!FAILED(hr));        
3888     }
3889 }
3890 #endif //FEATURE_CLASSIC_COMINTEROP
3891
3892
3893 //=======================================================================
3894 // function ptr <--> Delegate
3895 // See FieldMarshaler for details.
3896 //=======================================================================
3897 VOID FieldMarshaler_Delegate::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const 
3898 {
3899     CONTRACTL
3900     {
3901         THROWS;
3902         GC_TRIGGERS;
3903         MODE_COOPERATIVE;
3904         PRECONDITION(CheckPointer(pNativeValue));
3905     }
3906     CONTRACTL_END;
3907
3908     LPVOID fnPtr = COMDelegate::ConvertToCallback(*pCLRValue);
3909     
3910     // If there is no CleanupWorkList (i.e. a call from Marshal.StructureToPtr), we don't use it to manage delegate lifetime.
3911     // In that case, it falls on the user to manage the delegate lifetime. This is the cleanest way to do this since there is no well-defined
3912     // object lifetime for the unmanaged memory that the structure would be marshalled to in the Marshal.StructureToPtr case.
3913     if (*pCLRValue != NULL && ppCleanupWorkListOnStack != NULL)
3914     {
3915         // Call StubHelpers.AddToCleanupList to ensure the delegate is kept alive across the full native call.
3916         MethodDescCallSite AddToCleanupList(METHOD__STUBHELPERS__ADD_TO_CLEANUP_LIST_DELEGATE);
3917
3918         ARG_SLOT args[] =
3919         {
3920             (ARG_SLOT)ppCleanupWorkListOnStack,
3921             ObjToArgSlot(*pCLRValue)
3922         };
3923
3924         AddToCleanupList.Call(args);
3925     }
3926
3927     MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, fnPtr);
3928 }
3929
3930
3931 //=======================================================================
3932 // function ptr <--> Delegate
3933 // See FieldMarshaler for details.
3934 //=======================================================================
3935 VOID FieldMarshaler_Delegate::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const 
3936 {
3937     CONTRACTL
3938     {
3939         THROWS;
3940         GC_TRIGGERS;
3941         MODE_COOPERATIVE;
3942         PRECONDITION(CheckPointer(pNativeValue));
3943         PRECONDITION(CheckPointer(ppProtectedCLRValue));
3944     }
3945     CONTRACTL_END;
3946
3947     *ppProtectedCLRValue = COMDelegate::ConvertToDelegate((LPVOID)MAYBE_UNALIGNED_READ(pNativeValue, _PTR), GetMethodTable());
3948 }
3949
3950
3951 //=======================================================================
3952 // SafeHandle <--> Handle
3953 // See FieldMarshaler for details.
3954 //=======================================================================
3955 VOID FieldMarshaler_SafeHandle::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const 
3956 {
3957     CONTRACTL
3958     {
3959         THROWS;
3960         GC_TRIGGERS;
3961         MODE_COOPERATIVE;
3962         PRECONDITION(CheckPointer(pNativeValue));
3963         PRECONDITION(CheckPointer(ppCleanupWorkListOnStack, NULL_OK));
3964     }
3965     CONTRACTL_END;
3966
3967     SAFEHANDLE *pSafeHandleObj = ((SAFEHANDLE *)pCLRValue);
3968
3969     // A cleanup list MUST be specified in order for us to be able to marshal
3970     // the SafeHandle.
3971     if (ppCleanupWorkListOnStack == NULL)
3972         COMPlusThrow(kInvalidOperationException, IDS_EE_SH_FIELD_INVALID_OPERATION); 
3973
3974     if (*pSafeHandleObj == NULL)
3975         COMPlusThrow(kArgumentNullException, W("ArgumentNull_SafeHandle"));
3976
3977     // Call StubHelpers.AddToCleanupList to AddRef and schedule Release on this SafeHandle
3978     // This is realiable, i.e. the cleanup will happen if and only if the SH was actually AddRef'ed.
3979     MethodDescCallSite AddToCleanupList(METHOD__STUBHELPERS__ADD_TO_CLEANUP_LIST_SAFEHANDLE);
3980
3981     ARG_SLOT args[] =
3982     {
3983         (ARG_SLOT)ppCleanupWorkListOnStack,
3984         ObjToArgSlot(*pSafeHandleObj)
3985     };
3986
3987     LPVOID handle = AddToCleanupList.Call_RetLPVOID(args);
3988
3989     MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, handle);
3990 }
3991
3992
3993 //=======================================================================
3994 // SafeHandle <--> Handle
3995 // See FieldMarshaler for details.
3996 //=======================================================================
3997 VOID FieldMarshaler_SafeHandle::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const 
3998 {
3999     CONTRACTL
4000     {
4001         THROWS;
4002         GC_TRIGGERS;
4003         MODE_COOPERATIVE;
4004         PRECONDITION(CheckPointer(pNativeValue));
4005         PRECONDITION(CheckPointer(ppProtectedCLRValue));
4006         PRECONDITION(CheckPointer(ppProtectedOldCLRValue));
4007     }
4008     CONTRACTL_END;
4009
4010     // Since we dissallow marshaling SafeHandle fields from unmanaged to managed, check
4011     // to see if this handle was obtained from a SafeHandle and if it was that the
4012     // handle value hasn't changed.
4013     SAFEHANDLE *pSafeHandleObj = (SAFEHANDLE *)ppProtectedOldCLRValue;
4014     if (!*pSafeHandleObj || (*pSafeHandleObj)->GetHandle() != (LPVOID)MAYBE_UNALIGNED_READ(pNativeValue, _PTR))
4015         COMPlusThrow(kNotSupportedException, IDS_EE_CANNOT_CREATE_SAFEHANDLE_FIELD);
4016
4017     // Now that we know the handle hasn't changed we just copy set the new SafeHandle
4018     // to the old one.
4019     *ppProtectedCLRValue = *ppProtectedOldCLRValue;
4020 }
4021
4022
4023 //=======================================================================
4024 // CriticalHandle <--> Handle
4025 // See FieldMarshaler for details.
4026 //=======================================================================
4027 VOID FieldMarshaler_CriticalHandle::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const 
4028 {
4029     CONTRACTL
4030     {
4031         THROWS;
4032         GC_TRIGGERS;
4033         MODE_COOPERATIVE;
4034         PRECONDITION(CheckPointer(pNativeValue));
4035     }
4036     CONTRACTL_END;
4037
4038     LPVOID handle = ((CRITICALHANDLE)*pCLRValue)->GetHandle();
4039     MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, handle);
4040 }
4041
4042
4043 //=======================================================================
4044 // CriticalHandle <--> Handle
4045 // See FieldMarshaler for details.
4046 //=======================================================================
4047 VOID FieldMarshaler_CriticalHandle::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const 
4048 {
4049     CONTRACTL
4050     {
4051         THROWS;
4052         GC_TRIGGERS;
4053         MODE_COOPERATIVE;
4054         PRECONDITION(CheckPointer(pNativeValue));
4055         PRECONDITION(CheckPointer(ppProtectedCLRValue));
4056         PRECONDITION(CheckPointer(ppProtectedOldCLRValue));
4057     }
4058     CONTRACTL_END;
4059
4060     // Since we dissallow marshaling CriticalHandle fields from unmanaged to managed, check
4061     // to see if this handle was obtained from a CriticalHandle and if it was that the
4062     // handle value hasn't changed.
4063     CRITICALHANDLE *pCriticalHandleObj = (CRITICALHANDLE *)ppProtectedOldCLRValue;
4064     if (!*pCriticalHandleObj || (*pCriticalHandleObj)->GetHandle() != (LPVOID)MAYBE_UNALIGNED_READ(pNativeValue, _PTR))
4065         COMPlusThrow(kNotSupportedException, IDS_EE_CANNOT_CREATE_CRITICALHANDLE_FIELD);
4066
4067     // Now that we know the handle hasn't changed we just copy set the new CriticalHandle
4068     // to the old one.
4069     *ppProtectedCLRValue = *ppProtectedOldCLRValue;
4070 }
4071
4072 #ifdef FEATURE_COMINTEROP
4073
4074 //=======================================================================
4075 // COM IP <--> interface
4076 // See FieldMarshaler for details.
4077 //=======================================================================
4078 VOID FieldMarshaler_Interface::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const 
4079 {
4080     CONTRACTL
4081     {
4082         THROWS;
4083         GC_TRIGGERS;
4084         MODE_COOPERATIVE;
4085         PRECONDITION(CheckPointer(pNativeValue));
4086     }
4087     CONTRACTL_END;
4088
4089     IUnknown *pUnk = NULL;
4090
4091     if (!m_pItfMT.IsNull())
4092     {
4093         pUnk = GetComIPFromObjectRef(pCLRValue, GetInterfaceMethodTable());
4094     }
4095     else if (!(m_dwFlags & ItfMarshalInfo::ITF_MARSHAL_USE_BASIC_ITF))
4096     {
4097         pUnk = GetComIPFromObjectRef(pCLRValue, GetMethodTable());
4098     }
4099     else
4100     {
4101         ComIpType ReqIpType = !!(m_dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF) ? ComIpType_Dispatch : ComIpType_Unknown;
4102         pUnk = GetComIPFromObjectRef(pCLRValue, ReqIpType, NULL);
4103     }
4104
4105     MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, pUnk);    
4106 }
4107
4108
4109 //=======================================================================
4110 // COM IP <--> interface
4111 // See FieldMarshaler for details.
4112 //=======================================================================
4113 VOID FieldMarshaler_Interface::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const 
4114 {
4115     CONTRACTL
4116     {
4117         THROWS;
4118         GC_TRIGGERS;
4119         MODE_COOPERATIVE;
4120         PRECONDITION(CheckPointer(pNativeValue));
4121         PRECONDITION(CheckPointer(ppProtectedCLRValue));
4122         PRECONDITION(IsProtectedByGCFrame(ppProtectedCLRValue));
4123     }
4124     CONTRACTL_END;
4125
4126     IUnknown *pUnk = (IUnknown*)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
4127
4128     MethodTable *pItfMT = GetInterfaceMethodTable();
4129     if (pItfMT != NULL && !pItfMT->IsInterface())
4130         pItfMT = NULL;
4131
4132     GetObjectRefFromComIP(
4133         ppProtectedCLRValue,                                    // Created object
4134         pUnk,                                                   // Interface pointer
4135         GetMethodTable(),                                       // Class MT
4136         pItfMT,                                                 // Interface MT
4137         (m_dwFlags & ItfMarshalInfo::ITF_MARSHAL_CLASS_IS_HINT) // Flags
4138     );
4139 }
4140
4141
4142 //=======================================================================
4143 // COM IP <--> interface
4144 // See FieldMarshaler for details.
4145 //=======================================================================
4146 VOID FieldMarshaler_Interface::DestroyNativeImpl(LPVOID pNativeValue) const 
4147 {
4148     CONTRACTL
4149     {
4150         NOTHROW;
4151         GC_TRIGGERS;
4152         MODE_ANY;
4153         PRECONDITION(CheckPointer(pNativeValue));
4154     }
4155     CONTRACTL_END;
4156
4157     IUnknown *pUnk = (IUnknown*)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
4158     MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
4159
4160     if (pUnk != NULL)
4161     {
4162         ULONG cbRef = SafeRelease(pUnk);
4163         LogInteropRelease(pUnk, cbRef, "Field marshaler destroy native");
4164     }
4165 }
4166
4167 #endif // FEATURE_COMINTEROP
4168
4169
4170 //=======================================================================
4171 // See FieldMarshaler for details.
4172 //=======================================================================
4173 VOID FieldMarshaler_Date::ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
4174 {
4175     CONTRACTL
4176     {
4177         THROWS;
4178         GC_TRIGGERS;
4179         MODE_COOPERATIVE;
4180         PRECONDITION(CheckPointer(pCLR));
4181         PRECONDITION(CheckPointer(pNative));
4182     }
4183     CONTRACTL_END;
4184
4185     // <TODO> Handle unaligned native fields </TODO>
4186     *((DATE*)pNative) =  COMDateTime::TicksToDoubleDate(*((INT64*)pCLR));
4187 }
4188
4189
4190 //=======================================================================
4191 // See FieldMarshaler for details.
4192 //=======================================================================
4193 VOID FieldMarshaler_Date::ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
4194 {
4195     CONTRACTL
4196     {
4197         THROWS;
4198         GC_TRIGGERS;
4199         MODE_COOPERATIVE;
4200         PRECONDITION(CheckPointer(pNative));
4201         PRECONDITION(CheckPointer(pCLR));
4202     }
4203     CONTRACTL_END;
4204
4205     // <TODO> Handle unaligned native fields </TODO>
4206     *((INT64*)pCLR) = COMDateTime::DoubleDateToTicks(*((DATE*)pNative));
4207 }
4208
4209
4210 #ifdef FEATURE_COMINTEROP
4211
4212 //=======================================================================
4213 // See FieldMarshaler for details.
4214 //=======================================================================
4215 VOID FieldMarshaler_Currency::ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
4216 {
4217     CONTRACTL
4218     {
4219         THROWS;
4220         GC_TRIGGERS;
4221         MODE_ANY;
4222         PRECONDITION(CheckPointer(pCLR));
4223         PRECONDITION(CheckPointer(pNative));
4224     }
4225     CONTRACTL_END;
4226
4227     // no need to switch to preemptive mode because it's very primitive operaion, doesn't take 
4228     // long and is guaranteed not to call 3rd party code. 
4229     // But if we do need to switch to preemptive mode, we can't pass the managed pointer to native code directly
4230     HRESULT hr = VarCyFromDec( (DECIMAL *)pCLR, (CURRENCY*)pNative);
4231     if (FAILED(hr))
4232         COMPlusThrowHR(hr);
4233
4234 }
4235
4236
4237 //=======================================================================
4238 // See FieldMarshaler for details.
4239 //=======================================================================
4240 VOID FieldMarshaler_Currency::ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
4241 {
4242     CONTRACTL
4243     {
4244         THROWS;
4245         GC_TRIGGERS;
4246         MODE_ANY;
4247         PRECONDITION(CheckPointer(pNative));
4248         PRECONDITION(CheckPointer(pCLR));
4249     }
4250     CONTRACTL_END;
4251
4252     // no need to switch to preemptive mode because it's very primitive operaion, doesn't take 
4253     // long and is guaranteed not to call 3rd party code. 
4254     // But if we do need to switch to preemptive mode, we can't pass the managed pointer to native code directly
4255     VarDecFromCyCanonicalize( *(CURRENCY*)pNative, (DECIMAL *)pCLR );
4256 }
4257
4258 VOID FieldMarshaler_DateTimeOffset::ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
4259 {
4260     CONTRACTL
4261     {
4262         THROWS;
4263         GC_TRIGGERS;
4264         MODE_COOPERATIVE;
4265         PRECONDITION(CheckPointer(pCLR));
4266         PRECONDITION(CheckPointer(pNative));
4267     }
4268     CONTRACTL_END;
4269
4270     MethodDescCallSite convertToNative(METHOD__DATETIMEOFFSETMARSHALER__CONVERT_TO_NATIVE);
4271     ARG_SLOT args[] =
4272     {
4273         PtrToArgSlot(pCLR),
4274         PtrToArgSlot(pNative)
4275     };
4276     convertToNative.Call(args);
4277 }
4278
4279 VOID FieldMarshaler_DateTimeOffset::ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
4280 {
4281     CONTRACTL
4282     {
4283         THROWS;
4284         GC_TRIGGERS;
4285         MODE_COOPERATIVE;
4286         PRECONDITION(CheckPointer(pNative));
4287         PRECONDITION(CheckPointer(pCLR));
4288     }
4289     CONTRACTL_END;
4290
4291     MethodDescCallSite convertToManaged(METHOD__DATETIMEOFFSETMARSHALER__CONVERT_TO_MANAGED);
4292     ARG_SLOT args[] =
4293     {
4294         PtrToArgSlot(pCLR),
4295         PtrToArgSlot(pNative)
4296     };
4297     convertToManaged.Call(args);
4298 }
4299
4300 #endif // FEATURE_COMINTEROP
4301
4302
4303 //=======================================================================
4304 // See FieldMarshaler for details.
4305 //=======================================================================
4306 VOID FieldMarshaler_Illegal::ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
4307 {
4308     CONTRACTL
4309     {
4310         THROWS;
4311         GC_TRIGGERS;
4312         MODE_COOPERATIVE;
4313         PRECONDITION(CheckPointer(pCLR));
4314         PRECONDITION(CheckPointer(pNative));
4315     }
4316     CONTRACTL_END;
4317
4318     DefineFullyQualifiedNameForClassW();
4319
4320     StackSString ssFieldName(SString::Utf8, GetFieldDesc()->GetName());
4321
4322     StackSString errorString(W("Unknown error."));
4323     errorString.LoadResource(CCompRC::Error, m_resIDWhy);
4324
4325     COMPlusThrow(kTypeLoadException, IDS_EE_BADMARSHALFIELD_ERROR_MSG,
4326                  GetFullyQualifiedNameForClassW(GetFieldDesc()->GetEnclosingMethodTable()),
4327                  ssFieldName.GetUnicode(), errorString.GetUnicode());
4328 }
4329
4330
4331 //=======================================================================
4332 // See FieldMarshaler for details.
4333 //=======================================================================
4334 VOID FieldMarshaler_Illegal::ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
4335 {
4336     CONTRACTL
4337     {
4338         THROWS;
4339         GC_TRIGGERS;
4340         MODE_COOPERATIVE;
4341         PRECONDITION(CheckPointer(pNative));
4342         PRECONDITION(CheckPointer(pCLR));
4343     }
4344     CONTRACTL_END;
4345
4346     DefineFullyQualifiedNameForClassW();
4347
4348     StackSString ssFieldName(SString::Utf8, GetFieldDesc()->GetName());
4349
4350     StackSString errorString(W("Unknown error."));
4351     errorString.LoadResource(CCompRC::Error,m_resIDWhy);
4352
4353     COMPlusThrow(kTypeLoadException, IDS_EE_BADMARSHALFIELD_ERROR_MSG, 
4354                  GetFullyQualifiedNameForClassW(GetFieldDesc()->GetEnclosingMethodTable()),
4355                  ssFieldName.GetUnicode(), errorString.GetUnicode());
4356 }
4357
4358 #ifdef FEATURE_COMINTEROP
4359
4360
4361 //=======================================================================
4362 // See FieldMarshaler for details.
4363 //=======================================================================
4364 VOID FieldMarshaler_Variant::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const 
4365 {
4366     CONTRACTL
4367     {
4368         THROWS;
4369         GC_TRIGGERS;
4370         MODE_COOPERATIVE;
4371         PRECONDITION(CheckPointer(pNativeValue));
4372     }
4373     CONTRACTL_END;
4374
4375     OleVariant::MarshalOleVariantForObject(pCLRValue, (VARIANT*)pNativeValue);
4376
4377 }
4378
4379
4380 //=======================================================================
4381 // See FieldMarshaler for details.
4382 //=======================================================================
4383 VOID FieldMarshaler_Variant::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const 
4384 {
4385     CONTRACTL
4386     {
4387         THROWS;
4388         GC_TRIGGERS;
4389         MODE_COOPERATIVE;
4390         PRECONDITION(CheckPointer(pNativeValue));
4391         PRECONDITION(CheckPointer(ppProtectedCLRValue));
4392     }
4393     CONTRACTL_END;
4394
4395     OleVariant::MarshalObjectForOleVariant((VARIANT*)pNativeValue, ppProtectedCLRValue);
4396 }
4397
4398
4399 //=======================================================================
4400 // See FieldMarshaler for details.
4401 //=======================================================================
4402 VOID FieldMarshaler_Variant::DestroyNativeImpl(LPVOID pNativeValue) const 
4403 {
4404     CONTRACTL
4405     {
4406         NOTHROW;
4407         GC_TRIGGERS;
4408         MODE_ANY;
4409         PRECONDITION(CheckPointer(pNativeValue));
4410     }
4411     CONTRACTL_END;
4412
4413     SafeVariantClear( (VARIANT*)pNativeValue );
4414 }
4415
4416 #endif // FEATURE_COMINTEROP
4417
4418 #endif // CROSSGEN_COMPILE
4419
4420
4421 //
4422 // Implementation of the virtual functions using switch statements.
4423 //
4424 // We are not able bake pointers to the FieldMarshaller vtables into NGen images. We store
4425 // the field marshaller id instead, and implement the virtualization by switch based on the id.
4426 //
4427
4428 #ifdef FEATURE_CLASSIC_COMINTEROP
4429 #define FieldMarshaler_SafeArray_Case(rettype, name, args) case NFT_SAFEARRAY: rettype ((FieldMarshaler_SafeArray*)this)->name##Impl args; break;
4430 #else
4431 #define FieldMarshaler_SafeArray_Case(rettype, name, args)
4432 #endif
4433
4434 #ifdef FEATURE_COMINTEROP
4435
4436 #define IMPLEMENT_FieldMarshaler_METHOD(ret, name, argsdecl, rettype, args) \
4437     ret FieldMarshaler::name argsdecl { \
4438         WRAPPER_NO_CONTRACT; \
4439         switch (GetNStructFieldType()) { \
4440         case NFT_STRINGUNI: rettype ((FieldMarshaler_StringUni*)this)->name##Impl args; break; \
4441         case NFT_STRINGANSI: rettype ((FieldMarshaler_StringAnsi*)this)->name##Impl args; break; \
4442         case NFT_STRINGUTF8: rettype ((FieldMarshaler_StringUtf8*)this)->name##Impl args; break; \
4443         case NFT_FIXEDSTRINGUNI: rettype ((FieldMarshaler_FixedStringUni*)this)->name##Impl args; break; \
4444         case NFT_FIXEDSTRINGANSI: rettype ((FieldMarshaler_FixedStringAnsi*)this)->name##Impl args; break; \
4445         case NFT_FIXEDCHARARRAYANSI: rettype ((FieldMarshaler_FixedCharArrayAnsi*)this)->name##Impl args; break; \
4446         case NFT_FIXEDARRAY: rettype ((FieldMarshaler_FixedArray*)this)->name##Impl args; break; \
4447         case NFT_DELEGATE: rettype ((FieldMarshaler_Delegate*)this)->name##Impl args; break; \
4448         case NFT_COPY1: rettype ((FieldMarshaler_Copy1*)this)->name##Impl args; break; \
4449         case NFT_COPY2: rettype ((FieldMarshaler_Copy2*)this)->name##Impl args; break; \
4450         case NFT_COPY4: rettype ((FieldMarshaler_Copy4*)this)->name##Impl args; break; \
4451         case NFT_COPY8: rettype ((FieldMarshaler_Copy8*)this)->name##Impl args; break; \
4452         case NFT_ANSICHAR: rettype ((FieldMarshaler_Ansi*)this)->name##Impl args; break; \
4453         case NFT_WINBOOL: rettype ((FieldMarshaler_WinBool*)this)->name##Impl args; break; \
4454         case NFT_NESTEDLAYOUTCLASS: rettype ((FieldMarshaler_NestedLayoutClass*)this)->name##Impl args; break; \
4455         case NFT_NESTEDVALUECLASS: rettype ((FieldMarshaler_NestedValueClass*)this)->name##Impl args; break; \
4456         case NFT_CBOOL: rettype ((FieldMarshaler_CBool*)this)->name##Impl args; break; \
4457         case NFT_DATE: rettype ((FieldMarshaler_Date*)this)->name##Impl args; break; \
4458         case NFT_DECIMAL: rettype ((FieldMarshaler_Decimal*)this)->name##Impl args; break; \
4459         case NFT_INTERFACE: rettype ((FieldMarshaler_Interface*)this)->name##Impl args; break; \
4460         case NFT_SAFEHANDLE: rettype ((FieldMarshaler_SafeHandle*)this)->name##Impl args; break; \
4461         case NFT_CRITICALHANDLE: rettype ((FieldMarshaler_CriticalHandle*)this)->name##Impl args; break; \
4462         FieldMarshaler_SafeArray_Case(rettype, name, args) \
4463         case NFT_BSTR: rettype ((FieldMarshaler_BSTR*)this)->name##Impl args; break; \
4464         case NFT_HSTRING: rettype ((FieldMarshaler_HSTRING*)this)->name##Impl args; break; \
4465         case NFT_VARIANT: rettype ((FieldMarshaler_Variant*)this)->name##Impl args; break; \
4466         case NFT_VARIANTBOOL: rettype ((FieldMarshaler_VariantBool*)this)->name##Impl args; break; \
4467         case NFT_CURRENCY: rettype ((FieldMarshaler_Currency*)this)->name##Impl args; break; \
4468         case NFT_DATETIMEOFFSET: rettype ((FieldMarshaler_DateTimeOffset*)this)->name##Impl args; break; \
4469         case NFT_SYSTEMTYPE: rettype ((FieldMarshaler_SystemType *)this)->name##Impl args; break; \
4470         case NFT_WINDOWSFOUNDATIONHRESULT: rettype ((FieldMarshaler_Exception*)this)->name##Impl args; break; \
4471         case NFT_WINDOWSFOUNDATIONIREFERENCE: rettype ((FieldMarshaler_Nullable*)this)->name##Impl args; break; \
4472         case NFT_ILLEGAL: rettype ((FieldMarshaler_Illegal*)this)->name##Impl args; break; \
4473         default: UNREACHABLE_MSG("unexpected type of FieldMarshaler"); break; \
4474         } \
4475     }
4476
4477 #else // FEATURE_COMINTEROP
4478
4479 #define IMPLEMENT_FieldMarshaler_METHOD(ret, name, argsdecl, rettype, args) \
4480     ret FieldMarshaler::name argsdecl { \
4481         WRAPPER_NO_CONTRACT; \
4482         switch (GetNStructFieldType()) { \
4483         case NFT_STRINGUNI: rettype ((FieldMarshaler_StringUni*)this)->name##Impl args; break; \
4484         case NFT_STRINGANSI: rettype ((FieldMarshaler_StringAnsi*)this)->name##Impl args; break; \
4485         case NFT_STRINGUTF8: rettype ((FieldMarshaler_StringUtf8*)this)->name##Impl args; break; \
4486         case NFT_FIXEDSTRINGUNI: rettype ((FieldMarshaler_FixedStringUni*)this)->name##Impl args; break; \
4487         case NFT_FIXEDSTRINGANSI: rettype ((FieldMarshaler_FixedStringAnsi*)this)->name##Impl args; break; \
4488         case NFT_FIXEDCHARARRAYANSI: rettype ((FieldMarshaler_FixedCharArrayAnsi*)this)->name##Impl args; break; \
4489         case NFT_FIXEDARRAY: rettype ((FieldMarshaler_FixedArray*)this)->name##Impl args; break; \
4490         case NFT_DELEGATE: rettype ((FieldMarshaler_Delegate*)this)->name##Impl args; break; \
4491         case NFT_COPY1: rettype ((FieldMarshaler_Copy1*)this)->name##Impl args; break; \
4492         case NFT_COPY2: rettype ((FieldMarshaler_Copy2*)this)->name##Impl args; break; \
4493         case NFT_COPY4: rettype ((FieldMarshaler_Copy4*)this)->name##Impl args; break; \
4494         case NFT_COPY8: rettype ((FieldMarshaler_Copy8*)this)->name##Impl args; break; \
4495         case NFT_ANSICHAR: rettype ((FieldMarshaler_Ansi*)this)->name##Impl args; break; \
4496         case NFT_WINBOOL: rettype ((FieldMarshaler_WinBool*)this)->name##Impl args; break; \
4497         case NFT_NESTEDLAYOUTCLASS: rettype ((FieldMarshaler_NestedLayoutClass*)this)->name##Impl args; break; \
4498         case NFT_NESTEDVALUECLASS: rettype ((FieldMarshaler_NestedValueClass*)this)->name##Impl args; break; \
4499         case NFT_CBOOL: rettype ((FieldMarshaler_CBool*)this)->name##Impl args; break; \
4500         case NFT_DATE: rettype ((FieldMarshaler_Date*)this)->name##Impl args; break; \
4501         case NFT_DECIMAL: rettype ((FieldMarshaler_Decimal*)this)->name##Impl args; break; \
4502         case NFT_SAFEHANDLE: rettype ((FieldMarshaler_SafeHandle*)this)->name##Impl args; break; \
4503         case NFT_CRITICALHANDLE: rettype ((FieldMarshaler_CriticalHandle*)this)->name##Impl args; break; \
4504         case NFT_BSTR: rettype ((FieldMarshaler_BSTR*)this)->name##Impl args; break; \
4505         case NFT_ILLEGAL: rettype ((FieldMarshaler_Illegal*)this)->name##Impl args; break; \
4506         default: UNREACHABLE_MSG("unexpected type of FieldMarshaler"); break; \
4507         } \
4508     }
4509
4510 #endif // FEATURE_COMINTEROP
4511
4512
4513 IMPLEMENT_FieldMarshaler_METHOD(UINT32, NativeSize,
4514     () const,
4515     return,
4516     ())
4517
4518 IMPLEMENT_FieldMarshaler_METHOD(UINT32, AlignmentRequirement,
4519     () const,
4520     return,
4521     ())
4522
4523 IMPLEMENT_FieldMarshaler_METHOD(BOOL, IsScalarMarshaler,
4524     () const,
4525     return,
4526     ())
4527
4528 IMPLEMENT_FieldMarshaler_METHOD(BOOL, IsNestedValueClassMarshaler,
4529     () const,
4530     return,
4531     ())
4532
4533 #ifndef CROSSGEN_COMPILE
4534 IMPLEMENT_FieldMarshaler_METHOD(VOID, UpdateNative,
4535     (OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const,
4536     ,
4537     (pCLRValue, pNativeValue, ppCleanupWorkListOnStack))
4538
4539 IMPLEMENT_FieldMarshaler_METHOD(VOID, UpdateCLR,
4540     (const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const,
4541     ,
4542     (pNativeValue, ppProtectedCLRValue, ppProtectedOldCLRValue))
4543
4544 IMPLEMENT_FieldMarshaler_METHOD(VOID, DestroyNative,
4545     (LPVOID pNativeValue) const,
4546     ,
4547     (pNativeValue))
4548
4549 IMPLEMENT_FieldMarshaler_METHOD(VOID, ScalarUpdateNative,
4550     (LPVOID pCLR, LPVOID pNative) const,
4551     return,
4552     (pCLR, pNative))
4553
4554 IMPLEMENT_FieldMarshaler_METHOD(VOID, ScalarUpdateCLR,
4555     (const VOID *pNative, LPVOID pCLR) const,
4556     return,
4557     (pNative, pCLR))
4558
4559 IMPLEMENT_FieldMarshaler_METHOD(VOID, NestedValueClassUpdateNative,
4560     (const VOID **ppProtectedCLR, SIZE_T startoffset, LPVOID pNative, OBJECTREF *ppCleanupWorkListOnStack) const,
4561     ,
4562     (ppProtectedCLR, startoffset, pNative, ppCleanupWorkListOnStack))
4563
4564 IMPLEMENT_FieldMarshaler_METHOD(VOID, NestedValueClassUpdateCLR,
4565     (const VOID *pNative, LPVOID *ppProtectedCLR, SIZE_T startoffset) const,
4566     ,
4567     (pNative, ppProtectedCLR, startoffset))
4568 #endif // CROSSGEN_COMPILE
4569
4570 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
4571 IMPLEMENT_FieldMarshaler_METHOD(void, Save,
4572     (DataImage *image),
4573     ,
4574     (image))
4575
4576 IMPLEMENT_FieldMarshaler_METHOD(void, Fixup,
4577     (DataImage *image),
4578     ,
4579     (image))
4580 #endif // FEATURE_NATIVE_IMAGE_GENERATION
4581
4582 IMPLEMENT_FieldMarshaler_METHOD(void, Restore,
4583     (),
4584     ,
4585     ())
4586
4587 #ifndef DACCESS_COMPILE
4588 IMPLEMENT_FieldMarshaler_METHOD(VOID, CopyTo,
4589     (VOID *pDest, SIZE_T destSize) const,
4590     ,
4591     (pDest, destSize))
4592 #endif // !DACCESS_COMPILE