Remove Marshaling MDA (#22579)
[platform/upstream/coreclr.git] / src / vm / fieldmarshaler.h
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.h
6 //
7
8 //
9 // FieldMarshalers are used to allow CLR programs to allocate and access
10 // native structures for interop purposes. FieldMarshalers are actually normal GC
11 // objects with a class, but instead of keeping fields in the GC object,
12 // it keeps a hidden pointer to a fixed memory block (which may have been
13 // allocated by a third party.) Field accesses to FieldMarshalers are redirected
14 // to this fixed block.
15 //
16
17
18 #ifndef __FieldMarshaler_h__
19 #define __FieldMarshaler_h__
20
21 #include "util.hpp"
22 #include "mlinfo.h"
23 #include "eeconfig.h"
24 #include "olevariant.h"
25
26 #ifdef FEATURE_COMINTEROP
27 #endif  // FEATURE_COMINTEROP
28
29 #ifdef FEATURE_PREJIT
30 #include "compile.h"
31 #endif // FEATURE_PREJIT
32
33 // Forward refernces
34 class EEClassLayoutInfo;
35 class FieldDesc;
36 class MethodTable;
37
38 class FieldMarshaler_NestedLayoutClass;
39 class FieldMarshaler_NestedValueClass;
40 class FieldMarshaler_StringUni;
41 class FieldMarshaler_StringAnsi;
42 class FieldMarshaler_FixedStringUni;
43 class FieldMarshaler_FixedStringAnsi;
44 class FieldMarshaler_FixedArray;
45 class FieldMarshaler_FixedCharArrayAnsi;
46 class FieldMarshaler_Delegate;
47 class FieldMarshaler_Illegal;
48 class FieldMarshaler_Copy1;
49 class FieldMarshaler_Copy2;
50 class FieldMarshaler_Copy4;
51 class FieldMarshaler_Copy8;
52 class FieldMarshaler_Ansi;
53 class FieldMarshaler_WinBool;
54 class FieldMarshaler_CBool;
55 class FieldMarshaler_Decimal;
56 class FieldMarshaler_Date;
57 class FieldMarshaler_BSTR;
58 #ifdef FEATURE_COMINTEROP
59 class FieldMarshaler_SafeArray;
60 class FieldMarshaler_HSTRING;
61 class FieldMarshaler_Interface;
62 class FieldMarshaler_Variant;
63 class FieldMarshaler_VariantBool;
64 class FieldMarshaler_DateTimeOffset;
65 class FieldMarshaler_SystemType;
66 class FieldMarshaler_Exception;
67 class FieldMarshaler_Nullable;
68 #endif // FEATURE_COMINTEROP
69
70 //=======================================================================
71 // Each possible COM+/Native pairing of data type has a
72 // NLF_* id. This is used to select the marshaling code.
73 //=======================================================================
74 #undef DEFINE_NFT
75 #define DEFINE_NFT(name, nativesize, fWinRTSupported) name,
76 enum NStructFieldType
77 {
78 #include "nsenums.h"
79     NFT_COUNT
80 };
81
82
83 //=======================================================================
84 // Magic number for default struct packing size.
85 //
86 // Currently we set this to the packing size of the largest supported
87 // fundamental type and let the field marshaller downsize where needed.
88 //=======================================================================
89 #define DEFAULT_PACKING_SIZE 32
90
91
92 //=======================================================================
93 // This is invoked from the class loader while building the data structures for a type.
94 // This function checks if explicit layout metadata exists.
95 //
96 // Returns:
97 //  TRUE    - yes, there's layout metadata
98 //  FALSE   - no, there's no layout.
99 //  fail    - throws a typeload exception
100 //
101 // If S_OK,
102 //   *pNLType            gets set to nltAnsi or nltUnicode
103 //   *pPackingSize       declared packing size
104 //   *pfExplicitoffsets  offsets explicit in metadata or computed?
105 //=======================================================================
106 BOOL HasLayoutMetadata(Assembly* pAssembly, IMDInternalImport *pInternalImport, mdTypeDef cl, 
107                             MethodTable *pParentMT, BYTE *pPackingSize, BYTE *pNLTType,
108                             BOOL *pfExplicitOffsets);
109
110
111 //=======================================================================
112 // This function returns TRUE if the type passed in is either a value class or a class and if it has layout information 
113 // and is marshalable. In all other cases it will return FALSE. 
114 //=======================================================================
115 BOOL IsStructMarshalable(TypeHandle th);
116
117 //=======================================================================
118 // The classloader stores an intermediate representation of the layout
119 // metadata in an array of these structures. The dual-pass nature
120 // is a bit extra overhead but building this structure requiring loading
121 // other classes (for nested structures) and I'd rather keep this
122 // next to the other places where we load other classes (e.g. the superclass
123 // and implemented interfaces.)
124 //
125 // Each redirected field gets one entry in LayoutRawFieldInfo.
126 // The array is terminated by one dummy record whose m_MD == mdMemberDefNil.
127 // WARNING!! Before you change this struct see the comment above the m_FieldMarshaler field
128 //=======================================================================
129 struct LayoutRawFieldInfo
130 {
131     mdFieldDef  m_MD;             // mdMemberDefNil for end of array
132     UINT8       m_nft;            // NFT_* value
133     UINT32      m_offset;         // native offset of field
134     UINT32      m_cbNativeSize;   // native size of field in bytes
135     ULONG       m_sequence;       // sequence # from metadata
136     BOOL        m_fIsOverlapped;
137
138
139     //----- Post v1.0 addition: The LayoutKind.Sequential attribute now affects managed layout as well.
140     //----- So we need to keep a parallel set of layout data for the managed side. The Size and AlignmentReq
141     //----- is redundant since we can figure it out from the sig but since we're already accessing the sig
142     //----- in ParseNativeType, we might as well capture it at that time.
143     UINT32      m_managedSize;    // managed size of field
144     UINT32      m_managedAlignmentReq; // natural alignment of field
145     UINT32      m_managedOffset;  // managed offset of field
146     UINT32      m_pad;            // needed to keep m_FieldMarshaler 8-byte aligned
147
148     // WARNING!
149     // We in-place create a field marshaler in the following
150     // memory, so keep it 8-byte aligned or 
151     // the vtable pointer initialization will cause a 
152     // misaligned memory write on IA64.
153     // The entire struct's size must also be multiple of 8 bytes
154     struct
155     {
156         private:
157             char m_space[MAXFIELDMARSHALERSIZE];
158     } m_FieldMarshaler;
159 };
160
161
162 //=======================================================================
163 // 
164 //=======================================================================
165
166 VOID LayoutUpdateNative(LPVOID *ppProtectedManagedData, SIZE_T offsetbias, MethodTable *pMT, BYTE* pNativeData, OBJECTREF *ppCleanupWorkListOnStack);
167 VOID LayoutUpdateCLR(LPVOID *ppProtectedManagedData, SIZE_T offsetbias, MethodTable *pMT, BYTE *pNativeData);
168 VOID LayoutDestroyNative(LPVOID pNative, MethodTable *pMT);
169
170 VOID FmtClassUpdateNative(OBJECTREF *ppProtectedManagedData, BYTE *pNativeData, OBJECTREF *ppCleanupWorkListOnStack);
171 VOID FmtClassUpdateCLR(OBJECTREF *ppProtectedManagedData, BYTE *pNativeData);
172 VOID FmtClassDestroyNative(LPVOID pNative, MethodTable *pMT);
173
174 VOID FmtValueTypeUpdateNative(LPVOID pProtectedManagedData, MethodTable *pMT, BYTE *pNativeData, OBJECTREF *ppCleanupWorkListOnStack);
175 VOID FmtValueTypeUpdateCLR(LPVOID pProtectedManagedData, MethodTable *pMT, BYTE *pNativeData);
176
177
178 //=======================================================================
179 // Abstract base class. Each type of NStruct reference field extends
180 // this class and implements the necessary methods.
181 //
182 //   UpdateNativeImpl
183 //       - this method receives a COM+ field value and a pointer to
184 //         native field inside the fixed portion. it should marshal
185 //         the COM+ value to a new native instance and store it
186 //         inside *pNativeValue. Do not destroy the value you overwrite
187 //         in *pNativeValue.
188 //
189 //         may throw COM+ exceptions
190 //
191 //   UpdateCLRImpl
192 //       - this method receives a read-only pointer to the native field inside
193 //         the fixed portion. it should marshal the native value to
194 //         a new CLR instance and store it in *ppCLRValue.
195 //         (the caller keeps *ppCLRValue gc-protected.)
196 //
197 //         may throw CLR exceptions
198 //
199 //   DestroyNativeImpl
200 //       - should do the type-specific deallocation of a native instance.
201 //         if the type has a "NULL" value, this method should
202 //         overwrite the field with this "NULL" value (whether or not
203 //         it does, however, it's considered a bug to depend on the
204 //         value left over after a DestroyNativeImpl.)
205 //
206 //         must NOT throw a CLR exception
207 //
208 //   NativeSizeImpl
209 //       - returns the size, in bytes, of the native version of the field.
210 //
211 //   AlignmentRequirementImpl
212 //       - returns one of 1,2,4 or 8; indicating the "natural" alignment
213 //         of the native field. In general,
214 //
215 //            for scalars, the AR is equal to the size
216 //            for arrays,  the AR is that of a single element
217 //            for structs, the AR is that of the member with the largest AR
218 //
219 //
220 //=======================================================================
221
222
223 #ifndef DACCESS_COMPILE
224
225 #define UNUSED_METHOD_IMPL(PROTOTYPE)                   \
226     PROTOTYPE                                           \
227     {                                                   \
228         LIMITED_METHOD_CONTRACT;                                  \
229         _ASSERTE(!"Not supposed to get here.");         \
230     }
231
232 #define ELEMENT_SIZE_IMPL(NativeSize, AlignmentReq)     \
233     UINT32 NativeSizeImpl() const                       \
234     {                                                   \
235         LIMITED_METHOD_CONTRACT;                                  \
236         return NativeSize;                              \
237     }                                                   \
238     UINT32 AlignmentRequirementImpl() const             \
239     {                                                   \
240         LIMITED_METHOD_CONTRACT;                                  \
241         return AlignmentReq;                            \
242     }
243
244 #define SCALAR_MARSHALER_IMPL(NativeSize, AlignmentReq) \
245     BOOL IsScalarMarshalerImpl() const                  \
246     {                                                   \
247         LIMITED_METHOD_CONTRACT;                                  \
248         return TRUE;                                    \
249     }                                                   \
250     ELEMENT_SIZE_IMPL(NativeSize, AlignmentReq)
251
252 #define COPY_TO_IMPL_BASE_STRUCT_ONLY() \
253     VOID CopyToImpl(VOID *pDest, SIZE_T destSize) \
254     { \
255         static_assert(sizeof(*this) == sizeof(FieldMarshaler), \
256                       "Please, implement CopyToImpl for correct copy of field values"); \
257         \
258         FieldMarshaler::CopyToImpl(pDest, destSize); \
259     }
260
261 #define START_COPY_TO_IMPL(CLASS_NAME) \
262     VOID CopyToImpl(VOID *pDest, SIZE_T destSize) const \
263     { \
264         FieldMarshaler::CopyToImpl(pDest, destSize); \
265     \
266         CLASS_NAME *pDestFieldMarshaller = (std::remove_const<std::remove_pointer<decltype(this)>::type>::type *) pDest; \
267         _ASSERTE(sizeof(*pDestFieldMarshaller) <= destSize); \
268
269 #define END_COPY_TO_IMPL(CLASS_NAME) \
270         static_assert(std::is_same<CLASS_NAME *, decltype(pDestFieldMarshaller)>::value, \
271                       "Structure's name is required"); \
272     }
273
274
275 //=======================================================================
276 //
277 // FieldMarshaler's are constructed in place and replicated via bit-wise
278 // copy, so you can't have a destructor. Make sure you don't define a 
279 // destructor in derived classes!!
280 // We used to enforce this by defining a private destructor, by the C++
281 // compiler doesn't allow that anymore.
282 //
283 //=======================================================================
284
285 class FieldMarshaler
286 {
287 public:
288     VOID UpdateNative(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
289     VOID UpdateCLR(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
290     VOID DestroyNative(LPVOID pNativeValue) const;
291     UINT32 NativeSize() const;
292     UINT32 AlignmentRequirement() const;
293     BOOL IsScalarMarshaler() const;
294     BOOL IsNestedValueClassMarshaler() const;
295     VOID ScalarUpdateNative(LPVOID pCLR, LPVOID pNative) const;
296     VOID ScalarUpdateCLR(const VOID *pNative, LPVOID pCLR) const;
297     VOID NestedValueClassUpdateNative(const VOID **ppProtectedCLR, SIZE_T startoffset, LPVOID pNative, OBJECTREF *ppCleanupWorkListOnStack) const;
298     VOID NestedValueClassUpdateCLR(const VOID *pNative, LPVOID *ppProtectedCLR, SIZE_T startoffset) const;
299     VOID CopyTo(VOID *pDest, SIZE_T destSize) const;
300 #ifdef FEATURE_PREJIT
301     void Save(DataImage *image);
302     void Fixup(DataImage *image);
303 #endif // FEATURE_PREJIT
304     void Restore();
305
306     VOID DestroyNativeImpl(LPVOID pNativeValue) const
307     {
308         LIMITED_METHOD_CONTRACT;
309     }
310
311     BOOL IsScalarMarshalerImpl() const
312     {
313         LIMITED_METHOD_CONTRACT; 
314         return FALSE;
315     }
316
317     BOOL IsNestedValueClassMarshalerImpl() const
318     {
319         LIMITED_METHOD_CONTRACT; 
320         return FALSE;
321     }
322
323     UNUSED_METHOD_IMPL(VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const)
324     UNUSED_METHOD_IMPL(VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const)
325     UNUSED_METHOD_IMPL(VOID NestedValueClassUpdateNativeImpl(const VOID **ppProtectedCLR, SIZE_T startoffset, LPVOID pNative, OBJECTREF *ppCleanupWorkListOnStack) const)
326     UNUSED_METHOD_IMPL(VOID NestedValueClassUpdateCLRImpl(const VOID *pNative, LPVOID *ppProtectedCLR, SIZE_T startoffset) const)
327
328     // 
329     // Methods for saving & restoring in prejitted images:
330     //
331
332     NStructFieldType GetNStructFieldType() const
333     {
334         LIMITED_METHOD_CONTRACT;
335         return m_nft;
336     }
337
338     void SetNStructFieldType(NStructFieldType nft)
339     {
340         LIMITED_METHOD_CONTRACT;
341         m_nft = nft;
342     }
343
344 #ifdef FEATURE_PREJIT
345     void SaveImpl(DataImage *image)
346     {
347         STANDARD_VM_CONTRACT;
348     }
349
350     void FixupImpl(DataImage *image)
351     {
352         STANDARD_VM_CONTRACT;
353
354         image->FixupFieldDescPointer(this, &m_pFD);
355     }
356 #endif // FEATURE_PREJIT
357
358     void RestoreImpl()
359     {
360         CONTRACTL
361         {
362             THROWS;
363             GC_TRIGGERS;
364             MODE_ANY;
365         }
366         CONTRACTL_END;
367
368 #ifdef FEATURE_PREJIT
369         Module::RestoreFieldDescPointer(&m_pFD);
370 #endif // FEATURE_PREJIT
371     }
372
373     void CopyToImpl(VOID *pDest, SIZE_T destSize) const
374     {
375         FieldMarshaler *pDestFieldMarshaller = (FieldMarshaler *) pDest;
376
377         _ASSERTE(sizeof(*pDestFieldMarshaller) <= destSize);
378
379         pDestFieldMarshaller->SetFieldDesc(GetFieldDesc());
380         pDestFieldMarshaller->SetExternalOffset(GetExternalOffset());
381         pDestFieldMarshaller->SetNStructFieldType(GetNStructFieldType());
382     }
383
384     void SetFieldDesc(FieldDesc* pFD)
385     {
386         LIMITED_METHOD_CONTRACT;
387         m_pFD.SetValueMaybeNull(pFD);
388     }
389
390     FieldDesc* GetFieldDesc() const
391     {
392         CONTRACT (FieldDesc*)
393         {
394             NOTHROW;
395             GC_NOTRIGGER;
396             MODE_ANY;
397             POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
398         }
399         CONTRACT_END;
400
401         RETURN m_pFD.GetValueMaybeNull();
402     }
403
404     void SetExternalOffset(UINT32 dwExternalOffset)
405     {
406         LIMITED_METHOD_CONTRACT;
407         m_dwExternalOffset = dwExternalOffset;
408     }
409
410     UINT32 GetExternalOffset() const
411     {
412         LIMITED_METHOD_CONTRACT;
413         return m_dwExternalOffset;
414     }
415     
416 protected:
417     FieldMarshaler()
418     {
419         LIMITED_METHOD_CONTRACT;
420         
421 #ifdef _DEBUG
422         m_dwExternalOffset = 0xcccccccc;
423 #endif
424     }
425
426     static inline void RestoreHelper(RelativeFixupPointer<PTR_MethodTable> *ppMT)
427     {
428         CONTRACTL
429         {
430             THROWS;
431             GC_TRIGGERS;
432             MODE_ANY;
433             PRECONDITION(CheckPointer(ppMT));
434         }
435         CONTRACTL_END;
436
437 #ifdef FEATURE_PREJIT
438         Module::RestoreMethodTablePointer(ppMT);
439 #else // FEATURE_PREJIT
440         // without NGEN we only have to make sure that the type is fully loaded
441         ClassLoader::EnsureLoaded(ppMT->GetValue());
442 #endif // FEATURE_PREJIT
443     }
444
445 #ifdef _DEBUG
446     static inline BOOL IsRestoredHelper(const RelativeFixupPointer<PTR_MethodTable> &pMT)
447     {
448         WRAPPER_NO_CONTRACT;
449
450 #ifdef FEATURE_PREJIT
451         return pMT.IsNull() || (!pMT.IsTagged() && pMT.GetValue()->IsRestored());
452 #else // FEATURE_PREJIT
453         // putting the IsFullyLoaded check here is tempting but incorrect
454         return TRUE;
455 #endif // FEATURE_PREJIT
456     }
457 #endif // _DEBUG
458
459
460     RelativeFixupPointer<PTR_FieldDesc> m_pFD;      // FieldDesc
461     UINT32           m_dwExternalOffset;    // offset of field in the fixed portion
462     NStructFieldType m_nft;
463 };
464
465
466 //=======================================================================
467 // BSTR <--> System.String
468 //=======================================================================
469 class FieldMarshaler_BSTR : public FieldMarshaler
470 {
471 public:
472
473     VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
474     VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
475     VOID DestroyNativeImpl(LPVOID pNativeValue) const;
476
477     ELEMENT_SIZE_IMPL(sizeof(BSTR), sizeof(BSTR))
478     COPY_TO_IMPL_BASE_STRUCT_ONLY()
479 };
480
481 #ifdef FEATURE_COMINTEROP
482 //=======================================================================
483 // HSTRING <--> System.String
484 //=======================================================================
485 class FieldMarshaler_HSTRING : public FieldMarshaler
486 {
487 public:
488     VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
489     VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
490     VOID DestroyNativeImpl(LPVOID pNativeValue) const;
491
492     ELEMENT_SIZE_IMPL(sizeof(HSTRING), sizeof(HSTRING))
493     COPY_TO_IMPL_BASE_STRUCT_ONLY()
494 };
495
496 //=======================================================================
497 // Windows.Foundation.IReference`1 <--> System.Nullable`1
498 //=======================================================================
499 class FieldMarshaler_Nullable : public FieldMarshaler
500 {
501 public:
502
503     FieldMarshaler_Nullable(MethodTable* pMT)
504     {
505         m_pNullableTypeMT.SetValueMaybeNull(pMT);
506     }
507
508     BOOL IsNullableMarshalerImpl() const
509     {
510         LIMITED_METHOD_CONTRACT;
511         return TRUE;
512     }
513
514     //UnImplementedMethods.
515     UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
516     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
517
518     ELEMENT_SIZE_IMPL(sizeof(IUnknown*), sizeof(IUnknown*))
519
520     //ImplementedMethods
521     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const;
522     VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const;
523     VOID DestroyNativeImpl(const VOID* pNativeValue) const;
524     MethodDesc* GetMethodDescForGenericInstantiation(MethodDesc* pMD) const;
525
526     BOOL IsScalarMarshalerImpl() const
527     {
528         LIMITED_METHOD_CONTRACT; 
529         return TRUE;
530     }
531
532 #ifdef FEATURE_PREJIT
533     void FixupImpl(DataImage *image)
534     {
535         STANDARD_VM_CONTRACT;
536         
537         image->FixupMethodTablePointer(this, &m_pNullableTypeMT);
538
539         FieldMarshaler::FixupImpl(image);
540     }
541 #endif // FEATURE_PREJIT
542
543     void RestoreImpl()
544     {
545         CONTRACTL
546         {
547             THROWS;
548             GC_TRIGGERS;
549             MODE_ANY;
550         }
551         CONTRACTL_END;
552
553         RestoreHelper(&m_pNullableTypeMT);
554
555         FieldMarshaler::RestoreImpl();
556     }
557
558     START_COPY_TO_IMPL(FieldMarshaler_Nullable)
559     {
560         pDestFieldMarshaller->m_pNullableTypeMT.SetValueMaybeNull(GetMethodTable());
561     }
562     END_COPY_TO_IMPL(FieldMarshaler_Nullable)
563
564 #ifdef _DEBUG
565     BOOL IsRestored() const
566     {
567         WRAPPER_NO_CONTRACT;
568
569         return IsRestoredHelper(m_pNullableTypeMT);
570     }
571 #endif
572
573     MethodTable *GetMethodTable() const
574     {
575         CONTRACTL
576         {
577             NOTHROW;
578             GC_NOTRIGGER;
579             MODE_ANY;
580             PRECONDITION(IsRestored());
581         }
582         CONTRACTL_END;
583
584         return m_pNullableTypeMT.GetValue();
585     }
586
587 private:
588     RelativeFixupPointer<PTR_MethodTable> m_pNullableTypeMT;
589 };
590
591
592 //=======================================================================
593 // Windows.UI.Xaml.Interop.TypeName <--> System.Type
594 //=======================================================================
595 class FieldMarshaler_SystemType : public FieldMarshaler
596 {
597 public:
598     VOID UpdateNativeImpl(OBJECTREF * pCLRValue, LPVOID pNativeValue, OBJECTREF * ppCleanupWorkListOnStack) const;
599     VOID UpdateCLRImpl(const VOID * pNativeValue, OBJECTREF * ppProtectedCLRValue, OBJECTREF * ppProtectedOldCLRValue) const;
600     VOID DestroyNativeImpl(LPVOID pNativeValue) const;
601     
602     ELEMENT_SIZE_IMPL(sizeof(HSTRING), sizeof(HSTRING))
603     COPY_TO_IMPL_BASE_STRUCT_ONLY()
604 };
605
606 //=======================================================================
607 // Windows.Foundation.HResult <--> System.Exception
608 // Note: The WinRT struct has exactly 1 field, Value (an HRESULT)
609 //=======================================================================
610 class FieldMarshaler_Exception : public FieldMarshaler
611 {
612 public:
613     VOID UpdateNativeImpl(OBJECTREF * pCLRValue, LPVOID pNativeValue, OBJECTREF * ppCleanupWorkListOnStack) const;
614     VOID UpdateCLRImpl(const VOID * pNativeValue, OBJECTREF * ppProtectedCLRValue, OBJECTREF * ppProtectedOldCLRValue) const;
615     
616     ELEMENT_SIZE_IMPL(sizeof(HRESULT), sizeof(HRESULT))
617     COPY_TO_IMPL_BASE_STRUCT_ONLY()
618 };
619
620 #endif // FEATURE_COMINTEROP
621
622
623
624 //=======================================================================
625 // Embedded struct <--> LayoutClass
626 //=======================================================================
627 class FieldMarshaler_NestedLayoutClass : public FieldMarshaler
628 {
629 public:
630     FieldMarshaler_NestedLayoutClass(MethodTable *pMT)
631     {
632         WRAPPER_NO_CONTRACT;
633         m_pNestedMethodTable.SetValueMaybeNull(pMT);
634     }
635
636     VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
637     VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
638     VOID DestroyNativeImpl(LPVOID pNativeValue) const;
639
640     UINT32 NativeSizeImpl() const;
641     UINT32 AlignmentRequirementImpl() const;
642     
643 #ifdef FEATURE_PREJIT
644     void FixupImpl(DataImage *image)
645     {
646         STANDARD_VM_CONTRACT;
647         
648         image->FixupMethodTablePointer(this, &m_pNestedMethodTable);
649
650         FieldMarshaler::FixupImpl(image);
651     }
652 #endif // FEATURE_PREJIT
653
654     void RestoreImpl()
655     {
656         CONTRACTL
657         {
658             THROWS;
659             GC_TRIGGERS;
660             MODE_ANY;
661         }
662         CONTRACTL_END;
663
664         RestoreHelper(&m_pNestedMethodTable);
665
666         FieldMarshaler::RestoreImpl();
667     }
668
669     START_COPY_TO_IMPL(FieldMarshaler_NestedLayoutClass)
670     {
671         pDestFieldMarshaller->m_pNestedMethodTable.SetValueMaybeNull(GetMethodTable());
672     }
673     END_COPY_TO_IMPL(FieldMarshaler_NestedLayoutClass)
674
675 #ifdef _DEBUG
676     BOOL IsRestored() const
677     {
678         WRAPPER_NO_CONTRACT;
679
680         return IsRestoredHelper(m_pNestedMethodTable);
681     }
682 #endif
683
684     MethodTable *GetMethodTable() const
685     {
686         CONTRACTL
687         {
688             NOTHROW;
689             GC_NOTRIGGER;
690             MODE_ANY;
691             PRECONDITION(IsRestored());
692         }
693         CONTRACTL_END;
694
695         return m_pNestedMethodTable.GetValueMaybeNull();
696     }
697
698 private:
699     // MethodTable of nested FieldMarshaler.
700     RelativeFixupPointer<PTR_MethodTable> m_pNestedMethodTable;
701 };
702
703
704 //=======================================================================
705 // Embedded struct <--> ValueClass
706 //=======================================================================
707 class FieldMarshaler_NestedValueClass : public FieldMarshaler
708 {
709 public:
710 #ifndef _DEBUG
711     FieldMarshaler_NestedValueClass(MethodTable *pMT)
712 #else
713     FieldMarshaler_NestedValueClass(MethodTable *pMT, BOOL isFixedBuffer)
714 #endif
715     {
716         WRAPPER_NO_CONTRACT;
717         m_pNestedMethodTable.SetValueMaybeNull(pMT);
718 #ifdef _DEBUG
719         m_isFixedBuffer = isFixedBuffer;
720 #endif
721     }
722
723     BOOL IsNestedValueClassMarshalerImpl() const
724     {
725         LIMITED_METHOD_CONTRACT;
726         return TRUE;
727     }
728
729     UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
730     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
731
732     VOID DestroyNativeImpl(LPVOID pNativeValue) const;
733
734     UINT32 NativeSizeImpl() const;
735     UINT32 AlignmentRequirementImpl() const;
736     VOID NestedValueClassUpdateNativeImpl(const VOID **ppProtectedCLR, SIZE_T startoffset, LPVOID pNative, OBJECTREF *ppCleanupWorkListOnStack) const;
737     VOID NestedValueClassUpdateCLRImpl(const VOID *pNative, LPVOID *ppProtectedCLR, SIZE_T startoffset) const;
738
739 #ifdef FEATURE_PREJIT
740     void FixupImpl(DataImage *image)
741     { 
742         STANDARD_VM_CONTRACT;
743         
744         image->FixupMethodTablePointer(this, &m_pNestedMethodTable);
745
746         FieldMarshaler::FixupImpl(image);
747     }
748 #endif // FEATURE_PREJIT
749
750     void RestoreImpl()
751     {
752         CONTRACTL
753         {
754             THROWS;
755             GC_TRIGGERS;
756             MODE_ANY;
757         }
758         CONTRACTL_END;
759
760         RestoreHelper(&m_pNestedMethodTable);
761
762         FieldMarshaler::RestoreImpl();
763     }
764
765     START_COPY_TO_IMPL(FieldMarshaler_NestedValueClass)
766     {
767         pDestFieldMarshaller->m_pNestedMethodTable.SetValueMaybeNull(GetMethodTable());
768 #ifdef _DEBUG
769         pDestFieldMarshaller->m_isFixedBuffer = m_isFixedBuffer;
770 #endif
771     }
772     END_COPY_TO_IMPL(FieldMarshaler_NestedValueClass)
773
774 #ifdef _DEBUG
775     BOOL IsRestored() const
776     {
777         WRAPPER_NO_CONTRACT;
778
779         return IsRestoredHelper(m_pNestedMethodTable);
780     }
781 #endif
782
783     BOOL IsBlittable()
784     {
785         WRAPPER_NO_CONTRACT;
786         return GetMethodTable()->IsBlittable();
787     }
788
789     MethodTable *GetMethodTable() const
790     {
791         CONTRACTL
792         {
793             NOTHROW;
794             GC_NOTRIGGER;
795             MODE_ANY;
796             PRECONDITION(IsRestored());
797         }
798         CONTRACTL_END;
799
800         return m_pNestedMethodTable.GetValueMaybeNull();
801     }
802
803 #ifdef _DEBUG
804     BOOL IsFixedBuffer() const
805     {
806         return m_isFixedBuffer;
807     }
808 #endif
809
810
811 private:
812     // MethodTable of nested NStruct.
813     RelativeFixupPointer<PTR_MethodTable> m_pNestedMethodTable;
814 #ifdef _DEBUG
815     BOOL m_isFixedBuffer;
816 #endif
817 };
818
819
820 //=======================================================================
821 // LPWSTR <--> System.String
822 //=======================================================================
823 class FieldMarshaler_StringUni : public FieldMarshaler
824 {
825 public:
826
827     VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
828     VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
829     VOID DestroyNativeImpl(LPVOID pNativeValue) const;
830
831     ELEMENT_SIZE_IMPL(sizeof(LPWSTR), sizeof(LPWSTR))
832     COPY_TO_IMPL_BASE_STRUCT_ONLY()
833 };
834
835 //=======================================================================
836 // LPUTF8STR <--> System.String
837 //=======================================================================
838 class FieldMarshaler_StringUtf8 : public FieldMarshaler
839 {
840 public:
841
842         VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
843         VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
844         VOID DestroyNativeImpl(LPVOID pNativeValue) const;
845
846         ELEMENT_SIZE_IMPL(sizeof(LPSTR), sizeof(LPSTR))
847         COPY_TO_IMPL_BASE_STRUCT_ONLY()
848 };
849
850 //=======================================================================
851 // LPSTR <--> System.String
852 //=======================================================================
853 class FieldMarshaler_StringAnsi : public FieldMarshaler
854 {
855 public:
856     FieldMarshaler_StringAnsi(BOOL BestFit, BOOL ThrowOnUnmappableChar) : 
857         m_BestFitMap(!!BestFit), m_ThrowOnUnmappableChar(!!ThrowOnUnmappableChar)
858     {
859         WRAPPER_NO_CONTRACT;
860     }
861
862     VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
863     VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
864     VOID DestroyNativeImpl(LPVOID pNativeValue) const;
865
866     ELEMENT_SIZE_IMPL(sizeof(LPSTR), sizeof(LPSTR))
867     
868     BOOL GetBestFit()
869     {
870         LIMITED_METHOD_CONTRACT;
871         return m_BestFitMap;
872     }
873     
874     BOOL GetThrowOnUnmappableChar()
875     {
876         LIMITED_METHOD_CONTRACT;
877         return m_ThrowOnUnmappableChar;
878     }
879     
880     START_COPY_TO_IMPL(FieldMarshaler_StringAnsi)
881     {
882         pDestFieldMarshaller->m_BestFitMap = m_BestFitMap;
883         pDestFieldMarshaller->m_ThrowOnUnmappableChar = m_ThrowOnUnmappableChar;
884     }
885     END_COPY_TO_IMPL(FieldMarshaler_StringAnsi)
886
887 private:
888     bool m_BestFitMap:1;
889     bool m_ThrowOnUnmappableChar:1;
890 };
891
892
893 //=======================================================================
894 // Embedded LPWSTR <--> System.String
895 //=======================================================================
896 class FieldMarshaler_FixedStringUni : public FieldMarshaler
897 {
898 public:
899     VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
900     VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
901
902     ELEMENT_SIZE_IMPL(m_numchar * sizeof(WCHAR), sizeof(WCHAR))
903
904     FieldMarshaler_FixedStringUni(UINT32 numChar)
905     {
906         WRAPPER_NO_CONTRACT;
907         m_numchar = numChar;
908     }
909     
910     START_COPY_TO_IMPL(FieldMarshaler_FixedStringUni)
911     {
912         pDestFieldMarshaller->m_numchar = m_numchar;
913     }
914     END_COPY_TO_IMPL(FieldMarshaler_FixedStringUni)
915
916 private:
917     // # of characters for fixed strings
918     UINT32           m_numchar;
919 };
920
921
922 //=======================================================================
923 // Embedded LPSTR <--> System.String
924 //=======================================================================
925 class FieldMarshaler_FixedStringAnsi : public FieldMarshaler
926 {
927 public:
928     FieldMarshaler_FixedStringAnsi(UINT32 numChar, BOOL BestFitMap, BOOL ThrowOnUnmappableChar) :
929         m_numchar(numChar), m_BestFitMap(!!BestFitMap), m_ThrowOnUnmappableChar(!!ThrowOnUnmappableChar)
930     {
931         WRAPPER_NO_CONTRACT;
932     }
933
934     VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
935     VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
936
937     ELEMENT_SIZE_IMPL(m_numchar * sizeof(CHAR), sizeof(CHAR))
938     
939     BOOL GetBestFit()
940     {
941         LIMITED_METHOD_CONTRACT;
942         return m_BestFitMap;
943     }
944     
945     BOOL GetThrowOnUnmappableChar()
946     {
947         LIMITED_METHOD_CONTRACT;
948         return m_ThrowOnUnmappableChar;
949     }
950     
951     START_COPY_TO_IMPL(FieldMarshaler_FixedStringAnsi)
952     {
953         pDestFieldMarshaller->m_numchar = m_numchar;
954         pDestFieldMarshaller->m_BestFitMap = m_BestFitMap;
955         pDestFieldMarshaller->m_ThrowOnUnmappableChar = m_ThrowOnUnmappableChar;
956     }
957     END_COPY_TO_IMPL(FieldMarshaler_FixedStringAnsi)
958
959 private:
960     // # of characters for fixed strings
961     UINT32           m_numchar;
962     bool             m_BestFitMap:1;
963     bool             m_ThrowOnUnmappableChar:1;
964 };
965
966
967 //=======================================================================
968 // Embedded AnsiChar array <--> char[]
969 //=======================================================================
970 class FieldMarshaler_FixedCharArrayAnsi : public FieldMarshaler
971 {
972 public:
973     FieldMarshaler_FixedCharArrayAnsi(UINT32 numElems, BOOL BestFit, BOOL ThrowOnUnmappableChar) :
974         m_numElems(numElems), m_BestFitMap(!!BestFit), m_ThrowOnUnmappableChar(!!ThrowOnUnmappableChar)
975     {
976         WRAPPER_NO_CONTRACT;
977     }
978
979     VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
980     VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
981
982     ELEMENT_SIZE_IMPL(m_numElems * sizeof(CHAR), sizeof(CHAR))
983
984     BOOL GetBestFit()
985     {
986         LIMITED_METHOD_CONTRACT;
987         return m_BestFitMap;
988     }
989     
990     BOOL GetThrowOnUnmappableChar()
991     {
992         LIMITED_METHOD_CONTRACT;
993         return m_ThrowOnUnmappableChar;
994     }
995     
996     START_COPY_TO_IMPL(FieldMarshaler_FixedCharArrayAnsi)
997     {
998         pDestFieldMarshaller->m_numElems = m_numElems;
999         pDestFieldMarshaller->m_BestFitMap = m_BestFitMap;
1000         pDestFieldMarshaller->m_ThrowOnUnmappableChar = m_ThrowOnUnmappableChar;
1001     }
1002     END_COPY_TO_IMPL(FieldMarshaler_FixedCharArrayAnsi)
1003
1004 private:
1005     // # of elements for fixedchararray
1006     UINT32           m_numElems;
1007     bool             m_BestFitMap:1;
1008     bool             m_ThrowOnUnmappableChar:1;
1009 };
1010
1011
1012 //=======================================================================
1013 // Embedded arrays
1014 //=======================================================================
1015 class FieldMarshaler_FixedArray : public FieldMarshaler
1016 {
1017 public:
1018     FieldMarshaler_FixedArray(IMDInternalImport *pMDImport, mdTypeDef cl, UINT32 numElems, VARTYPE vt, MethodTable* pElementMT);
1019
1020     VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
1021     VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
1022     VOID DestroyNativeImpl(LPVOID pNativeValue) const;
1023     UINT32 AlignmentRequirementImpl() const;
1024
1025     UINT32 NativeSizeImpl() const
1026     {
1027         LIMITED_METHOD_CONTRACT;
1028
1029         return OleVariant::GetElementSizeForVarType(m_vt, GetElementMethodTable()) * m_numElems;
1030     }
1031
1032     MethodTable* GetElementMethodTable() const
1033     {
1034         return GetElementTypeHandle().GetMethodTable();
1035     }
1036
1037     TypeHandle GetElementTypeHandle() const
1038     {
1039         CONTRACTL
1040         {
1041             NOTHROW;
1042             GC_NOTRIGGER;
1043             MODE_ANY;
1044             PRECONDITION(IsRestored());
1045         }
1046         CONTRACTL_END;
1047         
1048         return m_arrayType.GetValue().AsArray()->GetArrayElementTypeHandle();
1049     }
1050     
1051     VARTYPE GetElementVT() const
1052     {
1053         LIMITED_METHOD_CONTRACT;
1054         return m_vt;
1055     }
1056
1057 #ifdef FEATURE_PREJIT
1058     void FixupImpl(DataImage *image)
1059     {
1060         STANDARD_VM_CONTRACT;
1061         
1062         image->FixupTypeHandlePointer(this, &m_arrayType);
1063
1064         FieldMarshaler::FixupImpl(image);
1065     }
1066 #endif // FEATURE_PREJIT
1067
1068     void RestoreImpl()
1069     {
1070         CONTRACTL
1071         {
1072             THROWS;
1073             GC_TRIGGERS;
1074             MODE_ANY;
1075         }
1076         CONTRACTL_END;
1077
1078 #ifdef FEATURE_PREJIT
1079         Module::RestoreTypeHandlePointer(&m_arrayType);
1080 #else // FEATURE_PREJIT
1081         // without NGEN we only have to make sure that the type is fully loaded
1082         ClassLoader::EnsureLoaded(m_arrayType.GetValue());
1083 #endif // FEATURE_PREJIT
1084         FieldMarshaler::RestoreImpl();
1085     }
1086
1087     START_COPY_TO_IMPL(FieldMarshaler_FixedArray)
1088     {
1089         pDestFieldMarshaller->m_arrayType.SetValueMaybeNull(m_arrayType.GetValueMaybeNull());
1090         pDestFieldMarshaller->m_numElems = m_numElems;
1091         pDestFieldMarshaller->m_vt = m_vt;
1092         pDestFieldMarshaller->m_BestFitMap = m_BestFitMap;
1093         pDestFieldMarshaller->m_ThrowOnUnmappableChar = m_ThrowOnUnmappableChar;
1094     }
1095     END_COPY_TO_IMPL(FieldMarshaler_FixedArray)
1096
1097 #ifdef _DEBUG
1098     BOOL IsRestored() const
1099     {
1100         WRAPPER_NO_CONTRACT;
1101
1102 #ifdef FEATURE_PREJIT
1103         return !m_arrayType.IsTagged() && (m_arrayType.IsNull() || m_arrayType.GetValue().IsRestored());
1104 #else // FEATURE_PREJIT
1105         return m_arrayType.IsNull() || m_arrayType.GetValue().IsFullyLoaded();
1106 #endif // FEATURE_PREJIT
1107     }
1108 #endif
1109    
1110 private:
1111     RelativeFixupPointer<TypeHandle> m_arrayType;
1112     UINT32           m_numElems;
1113     VARTYPE          m_vt;
1114     bool             m_BestFitMap:1; // Note: deliberately use small bools to save on working set - this is the largest FieldMarshaler and dominates the cost of the FieldMarshaler array
1115     bool             m_ThrowOnUnmappableChar:1; // Note: deliberately use small bools to save on working set - this is the largest FieldMarshaler and dominates the cost of the FieldMarshaler array
1116 };
1117
1118
1119 #ifdef FEATURE_CLASSIC_COMINTEROP
1120 //=======================================================================
1121 // SafeArrays
1122 //=======================================================================
1123 class FieldMarshaler_SafeArray : public FieldMarshaler
1124 {
1125 public:
1126
1127     VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
1128     VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
1129     VOID DestroyNativeImpl(LPVOID pNativeValue) const;
1130
1131     ELEMENT_SIZE_IMPL(sizeof(LPSAFEARRAY), sizeof(LPSAFEARRAY))
1132
1133     FieldMarshaler_SafeArray(VARTYPE vt, MethodTable* pMT)
1134     {
1135         WRAPPER_NO_CONTRACT;
1136         m_vt = vt;
1137         m_pMT.SetValueMaybeNull(pMT);
1138     }
1139
1140 #ifdef FEATURE_PREJIT
1141     void FixupImpl(DataImage *image)
1142     { 
1143         STANDARD_VM_CONTRACT;
1144         
1145         image->FixupMethodTablePointer(this, &m_pMT);
1146
1147         FieldMarshaler::FixupImpl(image);
1148     }
1149 #endif // FEATURE_PREJIT
1150
1151     void RestoreImpl()
1152     {
1153         CONTRACTL
1154         {
1155             THROWS;
1156             GC_TRIGGERS;
1157             MODE_ANY;
1158         }
1159         CONTRACTL_END;
1160
1161         RestoreHelper(&m_pMT);
1162
1163         FieldMarshaler::RestoreImpl();
1164     }
1165
1166     START_COPY_TO_IMPL(FieldMarshaler_SafeArray)
1167     {
1168         pDestFieldMarshaller->m_pMT.SetValueMaybeNull(m_pMT.GetValueMaybeNull());
1169         pDestFieldMarshaller->m_vt = m_vt;
1170     }
1171     END_COPY_TO_IMPL(FieldMarshaler_SafeArray)
1172
1173 #ifdef _DEBUG
1174     BOOL IsRestored() const
1175     {
1176         WRAPPER_NO_CONTRACT;
1177
1178         return IsRestoredHelper(m_pMT);
1179     }
1180 #endif
1181
1182     TypeHandle GetElementTypeHandle() const
1183     {
1184         CONTRACTL
1185         {
1186             NOTHROW;
1187             GC_NOTRIGGER;
1188             MODE_ANY;
1189             PRECONDITION(IsRestored());
1190         }
1191         CONTRACTL_END;
1192
1193         return TypeHandle(m_pMT.GetValue());
1194     }
1195
1196     VARTYPE GetElementVT() const
1197     {
1198         LIMITED_METHOD_CONTRACT;
1199         return m_vt;
1200     }
1201
1202 private:
1203     RelativeFixupPointer<PTR_MethodTable> m_pMT;
1204     VARTYPE          m_vt;
1205 };
1206 #endif //FEATURE_CLASSIC_COMINTEROP
1207
1208
1209 //=======================================================================
1210 // Embedded function ptr <--> Delegate
1211 //=======================================================================
1212 class FieldMarshaler_Delegate : public FieldMarshaler
1213 {
1214 public:
1215     FieldMarshaler_Delegate(MethodTable* pMT)
1216     {
1217         WRAPPER_NO_CONTRACT;
1218         m_pNestedMethodTable.SetValueMaybeNull(pMT);
1219     }
1220
1221     VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
1222     VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
1223
1224     ELEMENT_SIZE_IMPL(sizeof(LPVOID), sizeof(LPVOID))
1225
1226 #ifdef FEATURE_PREJIT
1227     void FixupImpl(DataImage *image)
1228     {
1229         STANDARD_VM_CONTRACT;
1230         
1231         image->FixupMethodTablePointer(this, &m_pNestedMethodTable);
1232
1233         FieldMarshaler::FixupImpl(image);
1234     }
1235 #endif // FEATURE_PREJIT
1236
1237     void RestoreImpl()
1238     {
1239         CONTRACTL
1240         {
1241             THROWS;
1242             GC_TRIGGERS;
1243             MODE_ANY;
1244         }
1245         CONTRACTL_END;
1246
1247         RestoreHelper(&m_pNestedMethodTable);
1248
1249         FieldMarshaler::RestoreImpl();
1250     }
1251
1252     START_COPY_TO_IMPL(FieldMarshaler_Delegate)
1253     {
1254         pDestFieldMarshaller->m_pNestedMethodTable.SetValueMaybeNull(m_pNestedMethodTable.GetValueMaybeNull());
1255     }
1256     END_COPY_TO_IMPL(FieldMarshaler_Delegate)
1257
1258 #ifdef _DEBUG
1259     BOOL IsRestored() const
1260     {
1261         WRAPPER_NO_CONTRACT;
1262
1263         return IsRestoredHelper(m_pNestedMethodTable);
1264     }
1265 #endif
1266
1267     MethodTable *GetMethodTable() const
1268     {
1269         CONTRACTL
1270         {
1271             NOTHROW;
1272             GC_NOTRIGGER;
1273             MODE_ANY;
1274             PRECONDITION(IsRestored());
1275         }
1276         CONTRACTL_END;
1277
1278         return m_pNestedMethodTable.GetValueMaybeNull();
1279     }
1280
1281     RelativeFixupPointer<PTR_MethodTable> m_pNestedMethodTable;
1282 };
1283
1284
1285 //=======================================================================
1286 // Embedded SafeHandle <--> Handle. This field really only supports
1287 // going from managed to unmanaged. In the other direction, we only
1288 // check that the handle value has not changed.
1289 //=======================================================================
1290 class FieldMarshaler_SafeHandle : public FieldMarshaler
1291 {
1292 public:
1293
1294     VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
1295     VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
1296
1297     ELEMENT_SIZE_IMPL(sizeof(LPVOID), sizeof(LPVOID))
1298     COPY_TO_IMPL_BASE_STRUCT_ONLY()
1299 };
1300
1301
1302 //=======================================================================
1303 // Embedded CriticalHandle <--> Handle. This field really only supports
1304 // going from managed to unmanaged. In the other direction, we only
1305 // check that the handle value has not changed.
1306 //=======================================================================
1307 class FieldMarshaler_CriticalHandle : public FieldMarshaler
1308 {
1309 public:
1310
1311     VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
1312     VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
1313
1314     ELEMENT_SIZE_IMPL(sizeof(LPVOID), sizeof(LPVOID))
1315     COPY_TO_IMPL_BASE_STRUCT_ONLY()
1316 };
1317
1318 #ifdef FEATURE_COMINTEROP
1319
1320 //=======================================================================
1321 // COM IP <--> Interface
1322 //=======================================================================
1323 class FieldMarshaler_Interface : public FieldMarshaler
1324 {
1325 public:
1326
1327     VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
1328     VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
1329     VOID DestroyNativeImpl(LPVOID pNativeValue) const;
1330
1331     ELEMENT_SIZE_IMPL(sizeof(IUnknown*), sizeof(IUnknown*))
1332
1333     FieldMarshaler_Interface(MethodTable *pClassMT, MethodTable *pItfMT, DWORD dwFlags)
1334     {
1335         WRAPPER_NO_CONTRACT;
1336         m_pClassMT.SetValueMaybeNull(pClassMT);
1337         m_pItfMT.SetValueMaybeNull(pItfMT);
1338         m_dwFlags = dwFlags;
1339     }
1340
1341 #ifdef FEATURE_PREJIT
1342     void FixupImpl(DataImage *image)
1343     {
1344         STANDARD_VM_CONTRACT;
1345         
1346         image->FixupMethodTablePointer(this, &m_pClassMT);
1347         image->FixupMethodTablePointer(this, &m_pItfMT);
1348
1349         FieldMarshaler::FixupImpl(image);
1350     }
1351 #endif // FEATURE_PREJIT
1352
1353     void RestoreImpl()
1354     {
1355         CONTRACTL
1356         {
1357             THROWS;
1358             GC_TRIGGERS;
1359             MODE_ANY;
1360         }
1361         CONTRACTL_END;
1362
1363         RestoreHelper(&m_pClassMT);
1364         RestoreHelper(&m_pItfMT);
1365
1366         FieldMarshaler::RestoreImpl();
1367     }
1368
1369     START_COPY_TO_IMPL(FieldMarshaler_Interface)
1370     {
1371         pDestFieldMarshaller->m_pClassMT.SetValueMaybeNull(m_pClassMT.GetValueMaybeNull());
1372         pDestFieldMarshaller->m_pItfMT.SetValueMaybeNull(m_pItfMT.GetValueMaybeNull());
1373         pDestFieldMarshaller->m_dwFlags = m_dwFlags;
1374     }
1375     END_COPY_TO_IMPL(FieldMarshaler_Interface)
1376
1377 #ifdef _DEBUG
1378     BOOL IsRestored() const
1379     {
1380         WRAPPER_NO_CONTRACT;
1381
1382         return (IsRestoredHelper(m_pClassMT) && IsRestoredHelper(m_pItfMT));
1383     }
1384 #endif
1385
1386     void GetInterfaceInfo(MethodTable **ppItfMT, DWORD* pdwFlags) const
1387     {
1388         CONTRACTL
1389         {
1390             NOTHROW;
1391             GC_NOTRIGGER;
1392             MODE_ANY;
1393             PRECONDITION(CheckPointer(ppItfMT));
1394 #ifdef FEATURE_PREJIT                                           
1395             PRECONDITION(IsRestored());
1396 #endif
1397         }
1398         CONTRACTL_END;
1399         
1400         *ppItfMT    = m_pItfMT.GetValue();
1401         *pdwFlags   = m_dwFlags;
1402     }
1403
1404     MethodTable *GetMethodTable() const
1405     {
1406         CONTRACTL
1407         {
1408             NOTHROW;
1409             GC_NOTRIGGER;
1410             MODE_ANY;
1411             PRECONDITION(IsRestored());
1412         }
1413         CONTRACTL_END;
1414
1415         return m_pClassMT.GetValueMaybeNull();
1416     }
1417
1418     MethodTable *GetInterfaceMethodTable() const
1419     {
1420         CONTRACTL
1421         {
1422             NOTHROW;
1423             GC_NOTRIGGER;
1424             MODE_ANY;
1425             PRECONDITION(IsRestored());
1426         }
1427         CONTRACTL_END;
1428
1429         return m_pItfMT.GetValueMaybeNull();
1430     }
1431
1432 private:
1433     RelativeFixupPointer<PTR_MethodTable> m_pClassMT;
1434     RelativeFixupPointer<PTR_MethodTable> m_pItfMT;
1435     DWORD           m_dwFlags;
1436 };
1437
1438 #endif // FEATURE_COMINTEROP
1439
1440 #ifdef FEATURE_COMINTEROP
1441 // This compile-time assert checks that the above FieldMarshaler is the biggest 
1442 // (or equal-biggest) FieldMasharler we have,
1443 // i.e. that we haven't set MAXFIELDMARSHALERSIZE to a value that is needlessly big.
1444 // Corresponding asserts in FieldMarshaler.cpp ensure that we haven't set it to a value that is needlessly
1445 // big, which would waste a whole lot of memory given the current storage scheme for FMs.
1446 //
1447 // If this assert first, it probably means you have successully reduced the size of the above FieldMarshaler.
1448 // You should now place this assert on the FieldMarshaler that is the biggest, or modify MAXFIELDMARSHALERSIZE
1449 // to match the new size.  
1450 static_assert_no_msg(sizeof(FieldMarshaler_Interface) == MAXFIELDMARSHALERSIZE); 
1451
1452 #endif // FEATURE_COMINTEROP
1453
1454 #ifdef FEATURE_COMINTEROP
1455
1456 //=======================================================================
1457 // VARIANT <--> Object
1458 //=======================================================================
1459 class FieldMarshaler_Variant : public FieldMarshaler
1460 {
1461 public:
1462
1463     VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
1464     VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
1465     VOID DestroyNativeImpl(LPVOID pNativeValue) const;
1466
1467     ELEMENT_SIZE_IMPL(sizeof(VARIANT), 8)
1468     COPY_TO_IMPL_BASE_STRUCT_ONLY()
1469 };
1470
1471 #endif // FEATURE_COMINTEROP
1472
1473
1474 //=======================================================================
1475 // Dummy marshaler
1476 //=======================================================================
1477 class FieldMarshaler_Illegal : public FieldMarshaler
1478 {
1479 public:
1480     FieldMarshaler_Illegal(UINT resIDWhy)
1481     {
1482         WRAPPER_NO_CONTRACT;
1483         m_resIDWhy = resIDWhy;
1484     }
1485
1486     UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
1487     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
1488
1489     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const;
1490     VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const;
1491
1492     SCALAR_MARSHALER_IMPL(1, 1)
1493
1494     START_COPY_TO_IMPL(FieldMarshaler_Illegal)
1495     {
1496         pDestFieldMarshaller->m_resIDWhy = m_resIDWhy;
1497     }
1498     END_COPY_TO_IMPL(FieldMarshaler_Illegal)
1499
1500 private:
1501     UINT m_resIDWhy;
1502 };
1503
1504
1505 #define FIELD_MARSHALER_COPY
1506
1507
1508 class FieldMarshaler_Copy1 : public FieldMarshaler
1509 {
1510 public: 
1511
1512     UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
1513     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
1514
1515     SCALAR_MARSHALER_IMPL(1, 1)
1516     COPY_TO_IMPL_BASE_STRUCT_ONLY()
1517
1518     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
1519     {
1520         CONTRACTL
1521         {
1522             NOTHROW;
1523             GC_NOTRIGGER;
1524             MODE_ANY;
1525             PRECONDITION(CheckPointer(pCLR));            
1526             PRECONDITION(CheckPointer(pNative));
1527         }
1528         CONTRACTL_END;
1529         
1530         *((U1*)pNative) = *((U1*)pCLR);
1531     }
1532
1533
1534     VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
1535     {
1536         CONTRACTL
1537         {
1538             NOTHROW;
1539             GC_NOTRIGGER;
1540             MODE_ANY;
1541             PRECONDITION(CheckPointer(pCLR));            
1542             PRECONDITION(CheckPointer(pNative));
1543         }
1544         CONTRACTL_END;
1545         
1546         *((U1*)pCLR) = *((U1*)pNative);
1547     }
1548
1549 };
1550
1551
1552
1553 class FieldMarshaler_Copy2 : public FieldMarshaler
1554 {
1555 public:
1556
1557     UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
1558     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
1559
1560     SCALAR_MARSHALER_IMPL(2, 2)
1561     COPY_TO_IMPL_BASE_STRUCT_ONLY()
1562
1563     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
1564     {
1565         CONTRACTL
1566         {
1567             NOTHROW;
1568             GC_NOTRIGGER;
1569             MODE_ANY;
1570             PRECONDITION(CheckPointer(pCLR));            
1571             PRECONDITION(CheckPointer(pNative));
1572         }
1573         CONTRACTL_END;
1574         
1575         MAYBE_UNALIGNED_WRITE(pNative, 16, MAYBE_UNALIGNED_READ(pCLR, 16));
1576     }
1577
1578
1579     VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
1580     {
1581         CONTRACTL
1582         {
1583             NOTHROW;
1584             GC_NOTRIGGER;
1585             MODE_ANY;
1586             PRECONDITION(CheckPointer(pCLR));            
1587             PRECONDITION(CheckPointer(pNative));
1588         }
1589         CONTRACTL_END;
1590         
1591         MAYBE_UNALIGNED_WRITE(pCLR, 16, MAYBE_UNALIGNED_READ(pNative, 16));
1592     }
1593
1594 };
1595
1596
1597 class FieldMarshaler_Copy4 : public FieldMarshaler
1598 {
1599 public:
1600
1601     UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
1602     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
1603
1604     SCALAR_MARSHALER_IMPL(4, 4)
1605     COPY_TO_IMPL_BASE_STRUCT_ONLY()
1606
1607     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
1608     {
1609         CONTRACTL
1610         {
1611             NOTHROW;
1612             GC_NOTRIGGER;
1613             MODE_ANY;
1614             PRECONDITION(CheckPointer(pCLR));            
1615             PRECONDITION(CheckPointer(pNative));
1616         }
1617         CONTRACTL_END;
1618         
1619         MAYBE_UNALIGNED_WRITE(pNative, 32, MAYBE_UNALIGNED_READ(pCLR, 32));
1620     }
1621
1622
1623     VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
1624     {
1625         CONTRACTL
1626         {
1627             NOTHROW;
1628             GC_NOTRIGGER;
1629             MODE_ANY;
1630             PRECONDITION(CheckPointer(pCLR));            
1631             PRECONDITION(CheckPointer(pNative));
1632         }
1633         CONTRACTL_END;
1634         
1635         MAYBE_UNALIGNED_WRITE(pCLR, 32, MAYBE_UNALIGNED_READ(pNative, 32));
1636     }
1637
1638 };
1639
1640
1641 class FieldMarshaler_Copy8 : public FieldMarshaler
1642 {
1643 public:
1644
1645     UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
1646     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
1647
1648 #if defined(_TARGET_X86_) && defined(UNIX_X86_ABI)
1649     // The System V ABI for i386 defines 4-byte alignment for 64-bit types.
1650     SCALAR_MARSHALER_IMPL(8, 4)
1651 #else
1652     SCALAR_MARSHALER_IMPL(8, 8)
1653 #endif // _TARGET_X86_
1654
1655     COPY_TO_IMPL_BASE_STRUCT_ONLY()
1656
1657     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
1658     {
1659         CONTRACTL
1660         {
1661             NOTHROW;
1662             GC_NOTRIGGER;
1663             MODE_ANY;
1664             PRECONDITION(CheckPointer(pCLR));            
1665             PRECONDITION(CheckPointer(pNative));
1666         }
1667         CONTRACTL_END;
1668         
1669         MAYBE_UNALIGNED_WRITE(pNative, 64, MAYBE_UNALIGNED_READ(pCLR, 64));
1670     }
1671
1672
1673     VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
1674     {
1675         CONTRACTL
1676         {
1677             NOTHROW;
1678             GC_NOTRIGGER;
1679             MODE_ANY;
1680             PRECONDITION(CheckPointer(pCLR));            
1681             PRECONDITION(CheckPointer(pNative));
1682         }
1683         CONTRACTL_END;
1684         
1685         MAYBE_UNALIGNED_WRITE(pCLR, 64, MAYBE_UNALIGNED_READ(pNative, 64));
1686     }
1687
1688 };
1689
1690
1691
1692 class FieldMarshaler_Ansi : public FieldMarshaler
1693 {
1694 public:
1695     FieldMarshaler_Ansi(BOOL BestFitMap, BOOL ThrowOnUnmappableChar) :
1696         m_BestFitMap(!!BestFitMap), m_ThrowOnUnmappableChar(!!ThrowOnUnmappableChar)
1697     {
1698         WRAPPER_NO_CONTRACT;
1699     }
1700
1701     UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
1702     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const) 
1703
1704     SCALAR_MARSHALER_IMPL(sizeof(CHAR), sizeof(CHAR))
1705
1706     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
1707     {
1708         CONTRACTL
1709         {
1710             THROWS;
1711             GC_TRIGGERS;
1712             MODE_ANY;
1713             PRECONDITION(CheckPointer(pCLR, NULL_OK));
1714             PRECONDITION(CheckPointer(pNative));
1715         }
1716         CONTRACTL_END;
1717       
1718         char c;
1719         InternalWideToAnsi((LPCWSTR)pCLR,
1720                            1,
1721                            &c,
1722                            1,
1723                            m_BestFitMap,
1724                            m_ThrowOnUnmappableChar);
1725         
1726         *((char*)pNative) = c;
1727     }
1728
1729     VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
1730     {
1731         CONTRACTL
1732         {
1733             NOTHROW;
1734             GC_NOTRIGGER;
1735             MODE_ANY;
1736             PRECONDITION(CheckPointer(pCLR));
1737             PRECONDITION(CheckPointer(pNative));
1738         }
1739         CONTRACTL_END;
1740       
1741         MultiByteToWideChar(CP_ACP, 0, (char*)pNative, 1, (LPWSTR)pCLR, 1);
1742     }
1743
1744     BOOL GetBestFit()
1745     {
1746         LIMITED_METHOD_CONTRACT;
1747         return m_BestFitMap;
1748     }
1749     
1750     BOOL GetThrowOnUnmappableChar()
1751     {
1752         LIMITED_METHOD_CONTRACT;
1753         return m_ThrowOnUnmappableChar;
1754     }
1755     
1756     START_COPY_TO_IMPL(FieldMarshaler_Ansi)
1757     {
1758         pDestFieldMarshaller->m_BestFitMap = m_BestFitMap;
1759         pDestFieldMarshaller->m_ThrowOnUnmappableChar = m_ThrowOnUnmappableChar;
1760     }
1761     END_COPY_TO_IMPL(FieldMarshaler_Ansi)
1762
1763 private:
1764     bool             m_BestFitMap:1;
1765     bool             m_ThrowOnUnmappableChar:1;
1766 };
1767
1768
1769
1770 class FieldMarshaler_WinBool : public FieldMarshaler
1771 {
1772 public:
1773
1774     UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
1775     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
1776
1777     SCALAR_MARSHALER_IMPL(sizeof(BOOL), sizeof(BOOL))
1778     COPY_TO_IMPL_BASE_STRUCT_ONLY()
1779
1780     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
1781     {
1782         CONTRACTL
1783         {
1784             THROWS;
1785             GC_NOTRIGGER;
1786             MODE_ANY;
1787             PRECONDITION(CheckPointer(pCLR));
1788             PRECONDITION(CheckPointer(pNative));
1789         }
1790         CONTRACTL_END;
1791         static_assert_no_msg(sizeof(BOOL) == sizeof(UINT32));
1792         MAYBE_UNALIGNED_WRITE(pNative, 32, ((*((U1 UNALIGNED*)pCLR)) ? 1 : 0));
1793     }
1794
1795
1796     VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
1797     {
1798         CONTRACTL
1799         {
1800             THROWS;
1801             GC_NOTRIGGER;
1802             MODE_ANY;
1803             PRECONDITION(CheckPointer(pCLR));
1804             PRECONDITION(CheckPointer(pNative));
1805         }
1806         CONTRACTL_END;
1807       
1808         static_assert_no_msg(sizeof(BOOL) == sizeof(UINT32));
1809         *((U1*)pCLR)  = MAYBE_UNALIGNED_READ(pNative, 32) ? 1 : 0;       
1810     }
1811
1812 };
1813
1814
1815
1816 #ifdef FEATURE_COMINTEROP
1817
1818 class FieldMarshaler_VariantBool : public FieldMarshaler
1819 {
1820 public:
1821
1822     UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
1823     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
1824
1825     SCALAR_MARSHALER_IMPL(sizeof(VARIANT_BOOL), sizeof(VARIANT_BOOL))
1826     COPY_TO_IMPL_BASE_STRUCT_ONLY()
1827
1828     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
1829     {
1830         CONTRACTL
1831         {
1832             THROWS;
1833             GC_NOTRIGGER;
1834             MODE_ANY;
1835             PRECONDITION(CheckPointer(pCLR));
1836             PRECONDITION(CheckPointer(pNative));
1837         }
1838         CONTRACTL_END;
1839
1840         static_assert_no_msg(sizeof(VARIANT_BOOL) == sizeof(BYTE) * 2);
1841
1842         MAYBE_UNALIGNED_WRITE(pNative, 16, (*((U1*)pCLR)) ? VARIANT_TRUE : VARIANT_FALSE);
1843     }
1844
1845
1846     VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
1847     {
1848         CONTRACTL
1849         {
1850             THROWS;
1851             GC_NOTRIGGER;
1852             MODE_ANY;
1853             PRECONDITION(CheckPointer(pCLR));
1854             PRECONDITION(CheckPointer(pNative));
1855         }
1856         CONTRACTL_END;
1857
1858         static_assert_no_msg(sizeof(VARIANT_BOOL) == sizeof(BYTE) * 2);
1859
1860         *((U1*)pCLR) = MAYBE_UNALIGNED_READ(pNative, 16) ? 1 : 0;
1861     }
1862
1863 };
1864
1865 #endif // FEATURE_COMINTEROP
1866
1867
1868
1869 class FieldMarshaler_CBool : public FieldMarshaler
1870 {
1871 public:
1872
1873     UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
1874     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
1875
1876     SCALAR_MARSHALER_IMPL(1, 1)
1877     COPY_TO_IMPL_BASE_STRUCT_ONLY()
1878
1879     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
1880     {
1881         CONTRACTL
1882         {
1883             THROWS;
1884             GC_NOTRIGGER;
1885             MODE_ANY;
1886             PRECONDITION(CheckPointer(pCLR));
1887             PRECONDITION(CheckPointer(pNative));
1888         }
1889         CONTRACTL_END;
1890
1891         *((U1*)pNative) = (*((U1*)pCLR)) ? 1 : 0;
1892     }
1893
1894     VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
1895     {
1896         CONTRACTL
1897         {
1898             THROWS;
1899             GC_NOTRIGGER;
1900             MODE_ANY;
1901             PRECONDITION(CheckPointer(pCLR));
1902             PRECONDITION(CheckPointer(pNative));
1903         }
1904         CONTRACTL_END;
1905       
1906         *((U1*)pCLR) = (*((U1*)pNative)) ? 1 : 0;
1907     }
1908
1909 };
1910
1911
1912 class FieldMarshaler_Decimal : public FieldMarshaler
1913 {
1914 public:
1915     UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
1916     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
1917
1918     SCALAR_MARSHALER_IMPL(sizeof(DECIMAL), 8);
1919     COPY_TO_IMPL_BASE_STRUCT_ONLY()
1920
1921     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
1922     {
1923         CONTRACTL
1924         {
1925             THROWS;
1926             GC_NOTRIGGER;
1927             MODE_ANY;
1928             PRECONDITION(CheckPointer(pCLR));
1929             PRECONDITION(CheckPointer(pNative));
1930         }
1931         CONTRACTL_END;
1932       
1933         memcpyNoGCRefs(pNative, pCLR, sizeof(DECIMAL));
1934     }
1935
1936     VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
1937     {
1938         CONTRACTL
1939         {
1940             THROWS;
1941             GC_NOTRIGGER;
1942             MODE_ANY;
1943             PRECONDITION(CheckPointer(pCLR));
1944             PRECONDITION(CheckPointer(pNative));
1945         }
1946         CONTRACTL_END;
1947       
1948         memcpyNoGCRefs(pCLR, pNative, sizeof(DECIMAL));
1949     }
1950
1951 };
1952
1953 class FieldMarshaler_Date : public FieldMarshaler
1954 {
1955 public:
1956
1957     UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
1958     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
1959
1960     SCALAR_MARSHALER_IMPL(sizeof(DATE), sizeof(DATE))
1961     COPY_TO_IMPL_BASE_STRUCT_ONLY()
1962
1963     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const;
1964     VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const;
1965
1966 };
1967
1968
1969
1970 #ifdef FEATURE_COMINTEROP
1971
1972 class FieldMarshaler_Currency : public FieldMarshaler
1973 {
1974 public:
1975
1976     UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
1977     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
1978
1979     SCALAR_MARSHALER_IMPL(sizeof(CURRENCY), sizeof(CURRENCY))
1980     COPY_TO_IMPL_BASE_STRUCT_ONLY()
1981
1982     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const;
1983     VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const;
1984
1985 };
1986
1987 class FieldMarshaler_DateTimeOffset : public FieldMarshaler
1988 {
1989 public:
1990
1991     UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
1992     UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
1993
1994     SCALAR_MARSHALER_IMPL(sizeof(INT64), sizeof(INT64))
1995     COPY_TO_IMPL_BASE_STRUCT_ONLY()
1996
1997     VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const;
1998     VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const;
1999
2000 };
2001
2002 #endif // FEATURE_COMINTEROP
2003
2004
2005 //========================================================================
2006 // Used to ensure that native data is properly deleted in exception cases.
2007 //========================================================================
2008 class NativeLayoutDestroyer
2009 {
2010 public:
2011     NativeLayoutDestroyer(BYTE* pNativeData, MethodTable* pMT, UINT32 cbSize)
2012     {
2013         CONTRACTL
2014         {
2015             NOTHROW;
2016             GC_NOTRIGGER;
2017             MODE_ANY;
2018             PRECONDITION(CheckPointer(pNativeData));
2019             PRECONDITION(CheckPointer(pMT));
2020         }
2021         CONTRACTL_END;
2022         
2023         m_pNativeData = pNativeData;
2024         m_pMT = pMT;
2025         m_cbSize = cbSize;
2026         m_fDestroy = TRUE;
2027     }
2028
2029     ~NativeLayoutDestroyer()
2030     {
2031         WRAPPER_NO_CONTRACT;
2032
2033         if (m_fDestroy)
2034         {
2035             LayoutDestroyNative(m_pNativeData, m_pMT);
2036             FillMemory(m_pNativeData, m_cbSize, 0);
2037         }
2038     }
2039
2040     void SuppressRelease()
2041     {
2042         m_fDestroy = FALSE;
2043     }
2044     
2045 private:
2046     NativeLayoutDestroyer()
2047     {
2048         LIMITED_METHOD_CONTRACT;
2049     }
2050
2051     BYTE*       m_pNativeData;
2052     MethodTable*    m_pMT;
2053     UINT32      m_cbSize;
2054     BOOL        m_fDestroy;
2055 };
2056
2057 #endif // DACCESS_COMPILE
2058
2059
2060 #endif // __FieldMarshaler_h__