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