diff options
Diffstat (limited to 'src/vm/object.h')
-rw-r--r-- | src/vm/object.h | 4675 |
1 files changed, 4675 insertions, 0 deletions
diff --git a/src/vm/object.h b/src/vm/object.h new file mode 100644 index 0000000000..37560cf53c --- /dev/null +++ b/src/vm/object.h @@ -0,0 +1,4675 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// OBJECT.H +// +// Definitions of a Com+ Object +// + +// See code:EEStartup#TableOfContents for overview + + +#ifndef _OBJECT_H_ +#define _OBJECT_H_ + +#include "util.hpp" +#include "syncblk.h" +#include "gcdesc.h" +#include "specialstatics.h" +#include "sstring.h" +#include "daccess.h" +#include "fcall.h" + +extern "C" void __fastcall ZeroMemoryInGCHeap(void*, size_t); + +void ErectWriteBarrierForMT(MethodTable **dst, MethodTable *ref); + +/* + #ObjectModel + * COM+ Internal Object Model + * + * + * Object - This is the common base part to all COM+ objects + * | it contains the MethodTable pointer and the + * | sync block index, which is at a negative offset + * | + * +-- code:StringObject - String objects are specialized objects for string + * | storage/retrieval for higher performance + * | + * +-- code:StringBufferObject - StringBuffer instance layout. + * | + * +-- BaseObjectWithCachedData - Object Plus one object field for caching. + * | | + * | +- ReflectClassBaseObject - The base object for the RuntimeType class + * | +- ReflectMethodObject - The base object for the RuntimeMethodInfo class + * | +- ReflectFieldObject - The base object for the RtFieldInfo class + * | + * +-- code:ArrayBase - Base portion of all arrays + * | | + * | +- I1Array - Base type arrays + * | | I2Array + * | | ... + * | | + * | +- PtrArray - Array of OBJECTREFs, different than base arrays because of pObjectClass + * | + * +-- code:AppDomainBaseObject - The base object for the class AppDomain + * | + * +-- code:AssemblyBaseObject - The base object for the class Assembly + * | + * +-- code:ContextBaseObject - base object for class Context + * + * + * PLEASE NOTE THE FOLLOWING WHEN ADDING A NEW OBJECT TYPE: + * + * The size of the object in the heap must be able to be computed + * very, very quickly for GC purposes. Restrictions on the layout + * of the object guarantee this is possible. + * + * Any object that inherits from Object must be able to + * compute its complete size by using the first 4 bytes of + * the object following the Object part and constants + * reachable from the MethodTable... + * + * The formula used for this calculation is: + * MT->GetBaseSize() + ((OBJECTTYPEREF->GetSizeField() * MT->GetComponentSize()) + * + * So for Object, since this is of fixed size, the ComponentSize is 0, which makes the right side + * of the equation above equal to 0 no matter what the value of GetSizeField(), so the size is just the base size. + * + */ + +// <TODO> +// @TODO: #define COW 0x04 +// @TODO: MOO, MOO - no, not bovine, really Copy On Write bit for StringBuffer, requires 8 byte align MT +// @TODL: which we don't have yet</TODO> + +class MethodTable; +class Thread; +class BaseDomain; +class Assembly; +class Context; +class CtxStaticData; +class DomainAssembly; +class AssemblyNative; +class WaitHandleNative; +class ArgDestination; + +struct RCW; + +#if CHECK_APP_DOMAIN_LEAKS + +class Object; + +class SetAppDomainAgilePendingTable +{ +public: + + SetAppDomainAgilePendingTable (); + ~SetAppDomainAgilePendingTable (); + + void PushReference (Object *pObject) + { + STATIC_CONTRACT_THROWS; + STATIC_CONTRACT_GC_NOTRIGGER; + + PendingEntry entry; + entry.pObject = pObject; + + m_Stack.Push(entry); + } + + void PushParent (Object *pObject) + { + STATIC_CONTRACT_THROWS; + STATIC_CONTRACT_GC_NOTRIGGER; + + PendingEntry entry; + entry.pObject = (Object*)((size_t)pObject | 1); + + m_Stack.Push(entry); + } + + Object *GetPendingObject (bool *pfReturnedToParent) + { + STATIC_CONTRACT_THROWS; + STATIC_CONTRACT_GC_NOTRIGGER; + + if (!m_Stack.Count()) + return NULL; + + PendingEntry *pPending = m_Stack.Pop(); + + *pfReturnedToParent = pPending->fMarked != 0; + return (Object*)((size_t)pPending->pObject & ~1); + } + +private: + + union PendingEntry + { + Object *pObject; + + // Indicates whether the current thread set BIT_SBLK_AGILE_IN_PROGRESS + // on the object. Entries without this flag set are unexplored + // objects. + size_t fMarked:1; + }; + + CStackArray<PendingEntry> m_Stack; +}; + +#endif //CHECK_APP_DOMAIN_LEAKS + + +// +// The generational GC requires that every object be at least 12 bytes +// in size. + +#define MIN_OBJECT_SIZE (2*sizeof(BYTE*) + sizeof(ObjHeader)) + +#define PTRALIGNCONST (DATA_ALIGNMENT-1) + +#ifndef PtrAlign +#define PtrAlign(size) \ + ((size + PTRALIGNCONST) & (~PTRALIGNCONST)) +#endif //!PtrAlign + +// code:Object is the respesentation of an managed object on the GC heap. +// +// See code:#ObjectModel for some important subclasses of code:Object +// +// The only fields mandated by all objects are +// +// * a pointer to the code:MethodTable at offset 0 +// * a poiner to a code:ObjHeader at a negative offset. This is often zero. It holds information that +// any addition information that we might need to attach to arbitrary objects. +// +class Object +{ + protected: + PTR_MethodTable m_pMethTab; + + protected: + Object() { LIMITED_METHOD_CONTRACT; }; + ~Object() { LIMITED_METHOD_CONTRACT; }; + + public: + MethodTable *RawGetMethodTable() const + { + return m_pMethTab; + } + +#ifndef DACCESS_COMPILE + void RawSetMethodTable(MethodTable *pMT) + { + LIMITED_METHOD_CONTRACT; + m_pMethTab = pMT; + } + + VOID SetMethodTable(MethodTable *pMT) + { + LIMITED_METHOD_CONTRACT; + m_pMethTab = pMT; + } + + VOID SetMethodTableForLargeObject(MethodTable *pMT) + { + // This function must be used if the allocation occurs on the large object heap, and the method table might be a collectible type + WRAPPER_NO_CONTRACT; + ErectWriteBarrierForMT(&m_pMethTab, pMT); + } + +#endif //!DACCESS_COMPILE + + // An object might be a proxy of some sort, with a thunking VTable. If so, we can + // advance to the true method table or class. + BOOL IsTransparentProxy() + { +#ifdef FEATURE_REMOTING + WRAPPER_NO_CONTRACT; + return( GetMethodTable()->IsTransparentProxy() ); +#else + LIMITED_METHOD_CONTRACT; + return FALSE; +#endif + } + +#define MARKED_BIT 0x1 + + PTR_MethodTable GetMethodTable() const + { + LIMITED_METHOD_DAC_CONTRACT; + +#ifndef DACCESS_COMPILE + // We should always use GetGCSafeMethodTable() if we're running during a GC. + // If the mark bit is set then we're running during a GC + _ASSERTE((dac_cast<TADDR>(m_pMethTab) & MARKED_BIT) == 0); + + return m_pMethTab; +#else //DACCESS_COMPILE + + //@dbgtodo dharvey Make this a type which supports bitwise and operations + //when available + return PTR_MethodTable((dac_cast<TADDR>(m_pMethTab)) & (~MARKED_BIT)); +#endif //DACCESS_COMPILE + } + + DPTR(PTR_MethodTable) GetMethodTablePtr() const + { + LIMITED_METHOD_CONTRACT; + return dac_cast<DPTR(PTR_MethodTable)>(PTR_HOST_MEMBER_TADDR(Object, this, m_pMethTab)); + } + + MethodTable *GetTrueMethodTable(); + + TypeHandle GetTypeHandle(); + TypeHandle GetTrueTypeHandle(); + + // Methods used to determine if an object supports a given interface. + static BOOL SupportsInterface(OBJECTREF pObj, MethodTable *pInterfaceMT); + + inline DWORD GetNumComponents(); + inline SIZE_T GetSize(); + + CGCDesc* GetSlotMap() + { + WRAPPER_NO_CONTRACT; + return( CGCDesc::GetCGCDescFromMT(GetMethodTable())); + } + + // Sync Block & Synchronization services + + // Access the ObjHeader which is at a negative offset on the object (because of + // cache lines) + PTR_ObjHeader GetHeader() + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast<PTR_ObjHeader>(this) - 1; + } + + // Get the current address of the object (works for debug refs, too.) + PTR_BYTE GetAddress() + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast<PTR_BYTE>(this); + } + +#ifdef _DEBUG + // TRUE if the header has a real SyncBlockIndex (i.e. it has an entry in the + // SyncTable, though it doesn't necessarily have an entry in the SyncBlockCache) + BOOL HasEmptySyncBlockInfo() + { + WRAPPER_NO_CONTRACT; + return GetHeader()->HasEmptySyncBlockInfo(); + } +#endif + + // retrieve or allocate a sync block for this object + SyncBlock *GetSyncBlock() + { + WRAPPER_NO_CONTRACT; + return GetHeader()->GetSyncBlock(); + } + + DWORD GetSyncBlockIndex() + { + WRAPPER_NO_CONTRACT; + return GetHeader()->GetSyncBlockIndex(); + } + + ADIndex GetAppDomainIndex(); + + // Get app domain of object, or NULL if it is agile + AppDomain *GetAppDomain(); + +#ifndef DACCESS_COMPILE + // Set app domain of object to current domain. + void SetAppDomain() { WRAPPER_NO_CONTRACT; SetAppDomain(::GetAppDomain()); } + BOOL SetAppDomainNoThrow(); + +#endif + + // Set app domain of object to given domain - it can only be set once + void SetAppDomain(AppDomain *pDomain); + +#ifdef _DEBUG +#ifndef DACCESS_COMPILE + // For SO-tolerance contract violation purposes, define these DEBUG_ versions to identify + // the codepaths to SetAppDomain that are called only from DEBUG code. + void DEBUG_SetAppDomain() + { + WRAPPER_NO_CONTRACT; + + DEBUG_SetAppDomain(::GetAppDomain()); + } +#endif //!DACCESS_COMPILE + + void DEBUG_SetAppDomain(AppDomain *pDomain); +#endif //_DEBUG + +#if CHECK_APP_DOMAIN_LEAKS + + // Mark object as app domain agile + BOOL SetAppDomainAgile(BOOL raiseAssert=TRUE, SetAppDomainAgilePendingTable *pTable = NULL); + BOOL TrySetAppDomainAgile(BOOL raiseAssert=TRUE); + + // Mark sync block as app domain agile + void SetSyncBlockAppDomainAgile(); + + // Check if object is app domain agile + BOOL IsAppDomainAgile(); + + // Check if object is app domain agile + BOOL IsAppDomainAgileRaw() + { + WRAPPER_NO_CONTRACT; + + SyncBlock *psb = PassiveGetSyncBlock(); + + return (psb && psb->IsAppDomainAgile()); + } + + BOOL IsCheckedForAppDomainAgile() + { + WRAPPER_NO_CONTRACT; + + SyncBlock *psb = PassiveGetSyncBlock(); + return (psb && psb->IsCheckedForAppDomainAgile()); + } + + void SetIsCheckedForAppDomainAgile() + { + WRAPPER_NO_CONTRACT; + + SyncBlock *psb = PassiveGetSyncBlock(); + if (psb) + psb->SetIsCheckedForAppDomainAgile(); + } + + // Check object to see if it is usable in the current domain + BOOL CheckAppDomain() { WRAPPER_NO_CONTRACT; return CheckAppDomain(::GetAppDomain()); } + + //Check object to see if it is usable in the given domain + BOOL CheckAppDomain(AppDomain *pDomain); + + // Check if the object's type is app domain agile + BOOL IsTypeAppDomainAgile(); + + // Check if the object's type is conditionally app domain agile + BOOL IsTypeCheckAppDomainAgile(); + + // Check if the object's type is naturally app domain agile + BOOL IsTypeTypesafeAppDomainAgile(); + + // Check if the object's type is possibly app domain agile + BOOL IsTypeNeverAppDomainAgile(); + + // Validate object & fields to see that it's usable from the current app domain + BOOL ValidateAppDomain() { WRAPPER_NO_CONTRACT; return ValidateAppDomain(::GetAppDomain()); } + + // Validate object & fields to see that it's usable from any app domain + BOOL ValidateAppDomainAgile() { WRAPPER_NO_CONTRACT; return ValidateAppDomain(NULL); } + + // Validate object & fields to see that it's usable from the given app domain (or null for agile) + BOOL ValidateAppDomain(AppDomain *pAppDomain); + + // Validate fields to see that they are usable from the object's app domain + // (or from any domain if the object is agile) + BOOL ValidateAppDomainFields() { WRAPPER_NO_CONTRACT; return ValidateAppDomainFields(GetAppDomain()); } + + // Validate fields to see that they are usable from the given app domain (or null for agile) + BOOL ValidateAppDomainFields(AppDomain *pAppDomain); + + // Validate a value type's fields to see that it's usable from the current app domain + static BOOL ValidateValueTypeAppDomain(MethodTable *pMT, void *base, BOOL raiseAssert = TRUE) + { WRAPPER_NO_CONTRACT; return ValidateValueTypeAppDomain(pMT, base, ::GetAppDomain(), raiseAssert); } + + // Validate a value type's fields to see that it's usable from any app domain + static BOOL ValidateValueTypeAppDomainAgile(MethodTable *pMT, void *base, BOOL raiseAssert = TRUE) + { WRAPPER_NO_CONTRACT; return ValidateValueTypeAppDomain(pMT, base, NULL, raiseAssert); } + + // Validate a value type's fields to see that it's usable from the given app domain (or null for agile) + static BOOL ValidateValueTypeAppDomain(MethodTable *pMT, void *base, AppDomain *pAppDomain, BOOL raiseAssert = TRUE); + + // Call when we are assigning this object to a dangerous field + // in an object in a given app domain (or agile if null) + BOOL AssignAppDomain(AppDomain *pAppDomain, BOOL raiseAssert = TRUE); + BOOL TryAssignAppDomain(AppDomain *pAppDomain, BOOL raiseAssert = TRUE); + + // Call when we are assigning to a dangerous value type field + // in an object in a given app domain (or agile if null) + static BOOL AssignValueTypeAppDomain(MethodTable *pMT, void *base, AppDomain *pAppDomain, BOOL raiseAssert = TRUE); + +#endif // CHECK_APP_DOMAIN_LEAKS + + // DO NOT ADD ANY ASSERTS TO THIS METHOD. + // DO NOT USE THIS METHOD. + // Yes folks, for better or worse the debugger pokes supposed object addresses + // to try to see if objects are valid, possibly firing an AccessViolation or worse, + // and then catches the AV and reports a failure to the debug client. This makes + // the debugger slightly more robust should any corrupted object references appear + // in a session. Thus it is "correct" behaviour for this to AV when used with + // an invalid object pointer, and incorrect behaviour for it to + // assert. + BOOL ValidateObjectWithPossibleAV(); + + // Validate an object ref out of the Promote routine in the GC + void ValidatePromote(ScanContext *sc, DWORD flags); + + // Validate an object ref out of the VerifyHeap routine in the GC + void ValidateHeap(Object *from, BOOL bDeep=TRUE); + + PTR_SyncBlock PassiveGetSyncBlock() + { + LIMITED_METHOD_DAC_CONTRACT; + return GetHeader()->PassiveGetSyncBlock(); + } + + static DWORD ComputeHashCode(); + +#ifndef DACCESS_COMPILE + INT32 GetHashCodeEx(); +#endif // #ifndef DACCESS_COMPILE + + // Synchronization +#ifndef DACCESS_COMPILE + + void EnterObjMonitor() + { + WRAPPER_NO_CONTRACT; + GetHeader()->EnterObjMonitor(); + } + + BOOL TryEnterObjMonitor(INT32 timeOut = 0) + { + WRAPPER_NO_CONTRACT; + return GetHeader()->TryEnterObjMonitor(timeOut); + } + + FORCEINLINE AwareLock::EnterHelperResult EnterObjMonitorHelper(Thread* pCurThread) + { + WRAPPER_NO_CONTRACT; + return GetHeader()->EnterObjMonitorHelper(pCurThread); + } + + FORCEINLINE AwareLock::EnterHelperResult EnterObjMonitorHelperSpin(Thread* pCurThread) + { + WRAPPER_NO_CONTRACT; + return GetHeader()->EnterObjMonitorHelperSpin(pCurThread); + } + + BOOL LeaveObjMonitor() + { + WRAPPER_NO_CONTRACT; + return GetHeader()->LeaveObjMonitor(); + } + + // should be called only from unwind code; used in the + // case where EnterObjMonitor failed to allocate the + // sync-object. + BOOL LeaveObjMonitorAtException() + { + WRAPPER_NO_CONTRACT; + return GetHeader()->LeaveObjMonitorAtException(); + } + + FORCEINLINE AwareLock::LeaveHelperAction LeaveObjMonitorHelper(Thread* pCurThread) + { + WRAPPER_NO_CONTRACT; + return GetHeader()->LeaveObjMonitorHelper(pCurThread); + } + + // Returns TRUE if the lock is owned and FALSE otherwise + // threadId is set to the ID (Thread::GetThreadId()) of the thread which owns the lock + // acquisitionCount is set to the number of times the lock needs to be released before + // it is unowned + BOOL GetThreadOwningMonitorLock(DWORD *pThreadId, DWORD *pAcquisitionCount) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + return GetHeader()->GetThreadOwningMonitorLock(pThreadId, pAcquisitionCount); + } + +#endif // #ifndef DACCESS_COMPILE + + BOOL Wait(INT32 timeOut, BOOL exitContext) + { + WRAPPER_NO_CONTRACT; + return GetHeader()->Wait(timeOut, exitContext); + } + + void Pulse() + { + WRAPPER_NO_CONTRACT; + GetHeader()->Pulse(); + } + + void PulseAll() + { + WRAPPER_NO_CONTRACT; + GetHeader()->PulseAll(); + } + + PTR_VOID UnBox(); // if it is a value class, get the pointer to the first field + + PTR_BYTE GetData(void) + { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + return dac_cast<PTR_BYTE>(this) + sizeof(Object); + } + + static UINT GetOffsetOfFirstField() + { + LIMITED_METHOD_CONTRACT; + return sizeof(Object); + } + + DWORD GetOffset32(DWORD dwOffset) + { + WRAPPER_NO_CONTRACT; + return * PTR_DWORD(GetData() + dwOffset); + } + + USHORT GetOffset16(DWORD dwOffset) + { + WRAPPER_NO_CONTRACT; + return * PTR_USHORT(GetData() + dwOffset); + } + + BYTE GetOffset8(DWORD dwOffset) + { + WRAPPER_NO_CONTRACT; + return * PTR_BYTE(GetData() + dwOffset); + } + + __int64 GetOffset64(DWORD dwOffset) + { + WRAPPER_NO_CONTRACT; + return (__int64) * PTR_ULONG64(GetData() + dwOffset); + } + + void *GetPtrOffset(DWORD dwOffset) + { + WRAPPER_NO_CONTRACT; + return (void *)(TADDR)*PTR_TADDR(GetData() + dwOffset); + } + +#ifndef DACCESS_COMPILE + + void SetOffsetObjectRef(DWORD dwOffset, size_t dwValue); + + void SetOffsetPtr(DWORD dwOffset, LPVOID value) + { + WRAPPER_NO_CONTRACT; + *(LPVOID *) &GetData()[dwOffset] = value; + } + + void SetOffset32(DWORD dwOffset, DWORD dwValue) + { + WRAPPER_NO_CONTRACT; + *(DWORD *) &GetData()[dwOffset] = dwValue; + } + + void SetOffset16(DWORD dwOffset, DWORD dwValue) + { + WRAPPER_NO_CONTRACT; + *(USHORT *) &GetData()[dwOffset] = (USHORT) dwValue; + } + + void SetOffset8(DWORD dwOffset, DWORD dwValue) + { + WRAPPER_NO_CONTRACT; + *(BYTE *) &GetData()[dwOffset] = (BYTE) dwValue; + } + + void SetOffset64(DWORD dwOffset, __int64 qwValue) + { + WRAPPER_NO_CONTRACT; + *(__int64 *) &GetData()[dwOffset] = qwValue; + } + +#endif // #ifndef DACCESS_COMPILE + + VOID Validate(BOOL bDeep = TRUE, BOOL bVerifyNextHeader = TRUE, BOOL bVerifySyncBlock = TRUE); + + PTR_MethodTable GetGCSafeMethodTable() const + { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + // lose GC marking bit and the pinning bit + // A method table pointer should always be aligned. During GC we set the least + // significant bit for marked objects and we set the second to least significant + // bit for pinned objects. So if we want the actual MT pointer during a GC + // we must zero out the lowest 2 bits. + return dac_cast<PTR_MethodTable>((dac_cast<TADDR>(m_pMethTab)) & ~((UINT_PTR)3)); + } + + // There are some cases where it is unsafe to get the type handle during a GC. + // This occurs when the type has already been unloaded as part of an in-progress appdomain shutdown. + TypeHandle GetGCSafeTypeHandleIfPossible() const; + + inline TypeHandle GetGCSafeTypeHandle() const; + +#ifdef DACCESS_COMPILE + void EnumMemoryRegions(void); +#endif + + private: + VOID ValidateInner(BOOL bDeep, BOOL bVerifyNextHeader, BOOL bVerifySyncBlock); + +#if CHECK_APP_DOMAIN_LEAKS + friend class ObjHeader; + BOOL SetFieldsAgile(BOOL raiseAssert = TRUE, SetAppDomainAgilePendingTable *pTable = NULL); + static BOOL SetClassFieldsAgile(MethodTable *pMT, void *base, BOOL baseIsVT, BOOL raiseAssert = TRUE, SetAppDomainAgilePendingTable *pTable = NULL); + static BOOL ValidateClassFields(MethodTable *pMT, void *base, BOOL baseIsVT, AppDomain *pAppDomain, BOOL raiseAssert = TRUE); + BOOL SetAppDomainAgileWorker(BOOL raiseAssert, SetAppDomainAgilePendingTable *pTable); + BOOL ShouldCheckAppDomainAgile(BOOL raiseAssert, BOOL *pfResult); +#endif + +}; + +/* + * Object ref setting routines. You must use these to do + * proper write barrier support, as well as app domain + * leak checking. + * + * Note that the AppDomain parameter is the app domain affinity + * of the object containing the field or value class. It should + * be NULL if the containing object is app domain agile. Note that + * you typically get this value by calling obj->GetAppDomain() on + * the containing object. + */ + +// SetObjectReference sets an OBJECTREF field + +void SetObjectReferenceUnchecked(OBJECTREF *dst,OBJECTREF ref); + +#ifdef _DEBUG +void EnableStressHeapHelper(); +#endif + +//Used to clear the object reference +inline void ClearObjectReference(OBJECTREF* dst) +{ + LIMITED_METHOD_CONTRACT; + *(void**)(dst) = NULL; +} + +// CopyValueClass sets a value class field + +void STDCALL CopyValueClassUnchecked(void* dest, void* src, MethodTable *pMT); +void STDCALL CopyValueClassArgUnchecked(ArgDestination *argDest, void* src, MethodTable *pMT, int destOffset); + +inline void InitValueClass(void *dest, MethodTable *pMT) +{ + WRAPPER_NO_CONTRACT; + ZeroMemoryInGCHeap(dest, pMT->GetNumInstanceFieldBytes()); +} + +// Initialize value class argument +void InitValueClassArg(ArgDestination *argDest, MethodTable *pMT); + +#if CHECK_APP_DOMAIN_LEAKS + +void SetObjectReferenceChecked(OBJECTREF *dst,OBJECTREF ref, AppDomain *pAppDomain); +void CopyValueClassChecked(void* dest, void* src, MethodTable *pMT, AppDomain *pAppDomain); +void CopyValueClassArgChecked(ArgDestination *argDest, void* src, MethodTable *pMT, AppDomain *pAppDomain, int destOffset); + +#define SetObjectReference(_d,_r,_a) SetObjectReferenceChecked(_d, _r, _a) +#define CopyValueClass(_d,_s,_m,_a) CopyValueClassChecked(_d,_s,_m,_a) +#define CopyValueClassArg(_d,_s,_m,_a,_o) CopyValueClassArgChecked(_d,_s,_m,_a,_o) + +#else + +#define SetObjectReference(_d,_r,_a) SetObjectReferenceUnchecked(_d, _r) +#define CopyValueClass(_d,_s,_m,_a) CopyValueClassUnchecked(_d,_s,_m) +#define CopyValueClassArg(_d,_s,_m,_a,_o) CopyValueClassArgUnchecked(_d,_s,_m,_o) + +#endif + +#include <pshpack4.h> + + +// There are two basic kinds of array layouts in COM+ +// ELEMENT_TYPE_ARRAY - a multidimensional array with lower bounds on the dims +// ELMENNT_TYPE_SZARRAY - A zero based single dimensional array +// +// In addition the layout of an array in memory is also affected by +// whether the method table is shared (eg in the case of arrays of object refs) +// or not. In the shared case, the array has to hold the type handle of +// the element type. +// +// ArrayBase encapuslates all of these details. In theory you should never +// have to peek inside this abstraction +// +class ArrayBase : public Object +{ + friend class GCHeap; + friend class CObjectHeader; + friend class Object; + friend OBJECTREF AllocateArrayEx(TypeHandle arrayClass, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap DEBUG_ARG(BOOL bDontSetAppDomain)); + friend OBJECTREF FastAllocatePrimitiveArray(MethodTable* arrayType, DWORD cElements, BOOL bAllocateInLargeHeap); + friend FCDECL2(Object*, JIT_NewArr1VC_MP_FastPortable, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size); + friend FCDECL2(Object*, JIT_NewArr1OBJ_MP_FastPortable, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size); + friend class JIT_TrialAlloc; + friend class CheckAsmOffsets; + friend struct _DacGlobals; + +private: + // This MUST be the first field, so that it directly follows Object. This is because + // Object::GetSize() looks at m_NumComponents even though it may not be an array (the + // values is shifted out if not an array, so it's ok). + DWORD m_NumComponents; +#ifdef _WIN64 + DWORD pad; +#endif // _WIN64 + + SVAL_DECL(INT32, s_arrayBoundsZero); // = 0 + + // What comes after this conceputally is: + // TypeHandle elementType; Only present if the method table is shared among many types (arrays of pointers) + // INT32 bounds[rank]; The bounds are only present for Multidimensional arrays + // INT32 lowerBounds[rank]; Valid indexes are lowerBounds[i] <= index[i] < lowerBounds[i] + bounds[i] + +public: + // Gets the unique type handle for this array object. + // This will call the loader in don't-load mode - the allocator + // always makes sure that the particular ArrayTypeDesc for this array + // type is available before allocating any instances of this array type. + inline TypeHandle GetTypeHandle() const; + + inline static TypeHandle GetTypeHandle(MethodTable * pMT); + + // Get the element type for the array, this works whether the the element + // type is stored in the array or not + inline TypeHandle GetArrayElementTypeHandle() const; + + // Get the CorElementType for the elements in the array. Avoids creating a TypeHandle + inline CorElementType GetArrayElementType() const; + + inline unsigned GetRank() const; + + // Total element count for the array + inline DWORD GetNumComponents() const; + + // Get pointer to elements, handles any number of dimensions + PTR_BYTE GetDataPtr(BOOL inGC = FALSE) const { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; +#ifdef _DEBUG +#ifndef DACCESS_COMPILE + EnableStressHeapHelper(); +#endif +#endif + return dac_cast<PTR_BYTE>(this) + + GetDataPtrOffset(inGC ? GetGCSafeMethodTable() : GetMethodTable()); + } + + // The component size is actually 16-bit WORD, but this method is returning SIZE_T to ensure + // that SIZE_T is used everywhere for object size computation. It is necessary to support + // objects bigger than 2GB. + SIZE_T GetComponentSize() const { + WRAPPER_NO_CONTRACT; + MethodTable * pMT; +#if CHECK_APP_DOMAIN_LEAKS + pMT = GetGCSafeMethodTable(); +#else + pMT = GetMethodTable(); +#endif //CHECK_APP_DOMAIN_LEAKS + _ASSERTE(pMT->HasComponentSize()); + return pMT->RawGetComponentSize(); + } + + // Note that this can be a multidimensional array of rank 1 + // (for example if we had a 1-D array with lower bounds + BOOL IsMultiDimArray() const { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + return(GetMethodTable()->IsMultiDimArray()); + } + + // Get pointer to the begining of the bounds (counts for each dim) + // Works for any array type + PTR_INT32 GetBoundsPtr() const { + WRAPPER_NO_CONTRACT; + MethodTable * pMT = GetMethodTable(); + if (pMT->IsMultiDimArray()) + { + return dac_cast<PTR_INT32>( + dac_cast<TADDR>(this) + sizeof(*this)); + } + else + { + return dac_cast<PTR_INT32>(PTR_HOST_MEMBER_TADDR(ArrayBase, this, + m_NumComponents)); + } + } + + // Works for any array type + PTR_INT32 GetLowerBoundsPtr() const { + WRAPPER_NO_CONTRACT; + if (IsMultiDimArray()) + { + // Lower bounds info is after total bounds info + // and total bounds info has rank elements + return GetBoundsPtr() + GetRank(); + } + else + return dac_cast<PTR_INT32>(GVAL_ADDR(s_arrayBoundsZero)); + } + + static unsigned GetOffsetOfNumComponents() { + LIMITED_METHOD_CONTRACT; + return offsetof(ArrayBase, m_NumComponents); + } + + inline static unsigned GetDataPtrOffset(MethodTable* pMT); + + inline static unsigned GetBoundsOffset(MethodTable* pMT); + inline static unsigned GetLowerBoundsOffset(MethodTable* pMT); +}; + +// +// Template used to build all the non-object +// arrays of a single dimension +// + +template < class KIND > +class Array : public ArrayBase +{ + public: + + typedef DPTR(KIND) PTR_KIND; + typedef DPTR(const KIND) PTR_CKIND; + + KIND m_Array[1]; + + PTR_KIND GetDirectPointerToNonObjectElements() + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + // return m_Array; + return PTR_KIND(GetDataPtr()); // This also handles arrays of dim 1 with lower bounds present + + } + + PTR_CKIND GetDirectConstPointerToNonObjectElements() const + { + WRAPPER_NO_CONTRACT; + // return m_Array; + return PTR_CKIND(GetDataPtr()); // This also handles arrays of dim 1 with lower bounds present + } +}; + + +// Warning: Use PtrArray only for single dimensional arrays, not multidim arrays. +class PtrArray : public ArrayBase +{ + friend class GCHeap; + friend class ClrDataAccess; + friend OBJECTREF AllocateArrayEx(TypeHandle arrayClass, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap); + friend class JIT_TrialAlloc; + friend class CheckAsmOffsets; + +public: + TypeHandle GetArrayElementTypeHandle() + { + LIMITED_METHOD_CONTRACT; + return GetMethodTable()->GetApproxArrayElementTypeHandle(); + } + + static SIZE_T GetDataOffset() + { + LIMITED_METHOD_CONTRACT; + return offsetof(PtrArray, m_Array); + } + + void SetAt(SIZE_T i, OBJECTREF ref) + { + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + SO_TOLERANT; + MODE_COOPERATIVE; + } + CONTRACTL_END; + _ASSERTE(i < GetNumComponents()); + SetObjectReference(m_Array + i, ref, GetAppDomain()); + } + + void ClearAt(SIZE_T i) + { + WRAPPER_NO_CONTRACT; + _ASSERTE(i < GetNumComponents()); + ClearObjectReference(m_Array + i); + } + + OBJECTREF GetAt(SIZE_T i) + { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + _ASSERTE(i < GetNumComponents()); + +// DAC doesn't know the true size of this array +// the compiler thinks it is size 1, but really it is size N hanging off the structure +#ifndef DACCESS_COMPILE + return m_Array[i]; +#else + TADDR arrayTargetAddress = dac_cast<TADDR>(this) + offsetof(PtrArray, m_Array); + __ArrayDPtr<OBJECTREF> targetArray = dac_cast< __ArrayDPtr<OBJECTREF> >(arrayTargetAddress); + return targetArray[i]; +#endif + } + + friend class StubLinkerCPU; +#ifdef FEATURE_ARRAYSTUB_AS_IL + friend class ArrayOpLinker; +#endif +public: + OBJECTREF m_Array[1]; +}; + +/* a TypedByRef is a structure that is used to implement VB's BYREF variants. + it is basically a tuple of an address of some data along with a TypeHandle + that indicates the type of the address */ +class TypedByRef +{ +public: + + PTR_VOID data; + TypeHandle type; +}; + +typedef DPTR(TypedByRef) PTR_TypedByRef; + +typedef Array<I1> I1Array; +typedef Array<I2> I2Array; +typedef Array<I4> I4Array; +typedef Array<I8> I8Array; +typedef Array<R4> R4Array; +typedef Array<R8> R8Array; +typedef Array<U1> U1Array; +typedef Array<U1> BOOLArray; +typedef Array<U2> U2Array; +typedef Array<WCHAR> CHARArray; +typedef Array<U4> U4Array; +typedef Array<U8> U8Array; +typedef PtrArray PTRArray; + +typedef DPTR(I1Array) PTR_I1Array; +typedef DPTR(I2Array) PTR_I2Array; +typedef DPTR(I4Array) PTR_I4Array; +typedef DPTR(I8Array) PTR_I8Array; +typedef DPTR(R4Array) PTR_R4Array; +typedef DPTR(R8Array) PTR_R8Array; +typedef DPTR(U1Array) PTR_U1Array; +typedef DPTR(BOOLArray) PTR_BOOLArray; +typedef DPTR(U2Array) PTR_U2Array; +typedef DPTR(CHARArray) PTR_CHARArray; +typedef DPTR(U4Array) PTR_U4Array; +typedef DPTR(U8Array) PTR_U8Array; +typedef DPTR(PTRArray) PTR_PTRArray; + +class StringObject; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<ArrayBase> BASEARRAYREF; +typedef REF<I1Array> I1ARRAYREF; +typedef REF<I2Array> I2ARRAYREF; +typedef REF<I4Array> I4ARRAYREF; +typedef REF<I8Array> I8ARRAYREF; +typedef REF<R4Array> R4ARRAYREF; +typedef REF<R8Array> R8ARRAYREF; +typedef REF<U1Array> U1ARRAYREF; +typedef REF<BOOLArray> BOOLARRAYREF; +typedef REF<U2Array> U2ARRAYREF; +typedef REF<U4Array> U4ARRAYREF; +typedef REF<U8Array> U8ARRAYREF; +typedef REF<CHARArray> CHARARRAYREF; +typedef REF<PTRArray> PTRARRAYREF; // Warning: Use PtrArray only for single dimensional arrays, not multidim arrays. +typedef REF<StringObject> STRINGREF; + +#else // USE_CHECKED_OBJECTREFS + +typedef PTR_ArrayBase BASEARRAYREF; +typedef PTR_I1Array I1ARRAYREF; +typedef PTR_I2Array I2ARRAYREF; +typedef PTR_I4Array I4ARRAYREF; +typedef PTR_I8Array I8ARRAYREF; +typedef PTR_R4Array R4ARRAYREF; +typedef PTR_R8Array R8ARRAYREF; +typedef PTR_U1Array U1ARRAYREF; +typedef PTR_BOOLArray BOOLARRAYREF; +typedef PTR_U2Array U2ARRAYREF; +typedef PTR_U4Array U4ARRAYREF; +typedef PTR_U8Array U8ARRAYREF; +typedef PTR_CHARArray CHARARRAYREF; +typedef PTR_PTRArray PTRARRAYREF; // Warning: Use PtrArray only for single dimensional arrays, not multidim arrays. +typedef PTR_StringObject STRINGREF; + +#endif // USE_CHECKED_OBJECTREFS + + +#include <poppack.h> + + +/* + * StringObject + * + * Special String implementation for performance. + * + * m_StringLength - Length of string in number of WCHARs + * m_Characters - The string buffer + * + */ + + +/** + * The high bit state can be one of three value: + * STRING_STATE_HIGH_CHARS: We've examined the string and determined that it definitely has values greater than 0x80 + * STRING_STATE_FAST_OPS: We've examined the string and determined that it definitely has no chars greater than 0x80 + * STRING_STATE_UNDETERMINED: We've never examined this string. + * We've also reserved another bit for future use. + */ + +#define STRING_STATE_UNDETERMINED 0x00000000 +#define STRING_STATE_HIGH_CHARS 0x40000000 +#define STRING_STATE_FAST_OPS 0x80000000 +#define STRING_STATE_SPECIAL_SORT 0xC0000000 + +#ifdef _MSC_VER +#pragma warning(disable : 4200) // disable zero-sized array warning +#endif +class StringObject : public Object +{ +#ifdef DACCESS_COMPILE + friend class ClrDataAccess; +#endif + friend class GCHeap; + friend class JIT_TrialAlloc; + friend class CheckAsmOffsets; + friend class COMString; + + private: + DWORD m_StringLength; + WCHAR m_Characters[0]; + // GC will see a StringObject like this: + // DWORD m_StringLength + // WCHAR m_Characters[0] + // DWORD m_OptionalPadding (this is an optional field and will appear based on need) + + public: + VOID SetStringLength(DWORD len) { LIMITED_METHOD_CONTRACT; _ASSERTE(len >= 0); m_StringLength = len; } + + protected: + StringObject() {LIMITED_METHOD_CONTRACT; } + ~StringObject() {LIMITED_METHOD_CONTRACT; } + + public: + static SIZE_T GetSize(DWORD stringLength); + + DWORD GetStringLength() { LIMITED_METHOD_DAC_CONTRACT; return( m_StringLength );} + WCHAR* GetBuffer() { LIMITED_METHOD_CONTRACT; _ASSERTE(this != nullptr); return (WCHAR*)( dac_cast<TADDR>(this) + offsetof(StringObject, m_Characters) ); } + WCHAR* GetBuffer(DWORD *pdwSize) { LIMITED_METHOD_CONTRACT; _ASSERTE((this != nullptr) && pdwSize); *pdwSize = GetStringLength(); return GetBuffer(); } + WCHAR* GetBufferNullable() { LIMITED_METHOD_CONTRACT; return( (this == nullptr) ? nullptr : (WCHAR*)( dac_cast<TADDR>(this) + offsetof(StringObject, m_Characters) ) ); } + + DWORD GetHighCharState() { + WRAPPER_NO_CONTRACT; + DWORD ret = GetHeader()->GetBits() & (BIT_SBLK_STRING_HIGH_CHAR_MASK); + return ret; + } + + VOID SetHighCharState(DWORD value) { + WRAPPER_NO_CONTRACT; + _ASSERTE(value==STRING_STATE_HIGH_CHARS || value==STRING_STATE_FAST_OPS + || value==STRING_STATE_UNDETERMINED || value==STRING_STATE_SPECIAL_SORT); + + // you need to clear the present state before going to a new state, but we'll allow multiple threads to set it to the same thing. + _ASSERTE((GetHighCharState() == STRING_STATE_UNDETERMINED) || (GetHighCharState()==value)); + + static_assert_no_msg(BIT_SBLK_STRING_HAS_NO_HIGH_CHARS == STRING_STATE_FAST_OPS && + STRING_STATE_HIGH_CHARS == BIT_SBLK_STRING_HIGH_CHARS_KNOWN && + STRING_STATE_SPECIAL_SORT == BIT_SBLK_STRING_HAS_SPECIAL_SORT); + + GetHeader()->SetBit(value); + } + + static UINT GetBufferOffset() + { + LIMITED_METHOD_DAC_CONTRACT; + return (UINT)(offsetof(StringObject, m_Characters)); + } + static UINT GetStringLengthOffset() + { + LIMITED_METHOD_CONTRACT; + return (UINT)(offsetof(StringObject, m_StringLength)); + } + VOID GetSString(SString &result) + { + WRAPPER_NO_CONTRACT; + result.Set(GetBuffer(), GetStringLength()); + } + //======================================================================== + // Creates a System.String object. All the functions that take a length + // or a count of bytes will add the null terminator after length + // characters. So this means that if you have a string that has 5 + // characters and the null terminator you should pass in 5 and NOT 6. + //======================================================================== + static STRINGREF NewString(int length); + static STRINGREF NewString(int length, BOOL bHasTrailByte); + static STRINGREF NewString(const WCHAR *pwsz); + static STRINGREF NewString(const WCHAR *pwsz, int length); + static STRINGREF NewString(LPCUTF8 psz); + static STRINGREF NewString(LPCUTF8 psz, int cBytes); + + static STRINGREF GetEmptyString(); + static STRINGREF* GetEmptyStringRefPtr(); + + static STRINGREF* InitEmptyStringRefPtr(); + + static STRINGREF __stdcall StringInitCharHelper(LPCSTR pszSource, int length); + DWORD InternalCheckHighChars(); + + BOOL HasTrailByte(); + BOOL GetTrailByte(BYTE *bTrailByte); + BOOL SetTrailByte(BYTE bTrailByte); + static BOOL CaseInsensitiveCompHelper(__in_ecount(aLength) WCHAR * strA, __in_z INT8 * strB, int aLength, int bLength, int *result); + +#ifdef VERIFY_HEAP + //has to use raw object to avoid recursive validation + BOOL ValidateHighChars (); +#endif //VERIFY_HEAP + + /*=================RefInterpretGetStringValuesDangerousForGC====================== + **N.B.: This perfoms no range checking and relies on the caller to have done this. + **Args: (IN)ref -- the String to be interpretted. + ** (OUT)chars -- a pointer to the characters in the buffer. + ** (OUT)length -- a pointer to the length of the buffer. + **Returns: void. + **Exceptions: None. + ==============================================================================*/ + // !!!! If you use this function, you have to be careful because chars is a pointer + // !!!! to the data buffer of ref. If GC happens after this call, you need to make + // !!!! sure that you have a pin handle on ref, or use GCPROTECT_BEGINPINNING on ref. + void RefInterpretGetStringValuesDangerousForGC(__deref_out_ecount(*length + 1) WCHAR **chars, int *length) { + WRAPPER_NO_CONTRACT; + + _ASSERTE(GetGCSafeMethodTable() == g_pStringClass); + *length = GetStringLength(); + *chars = GetBuffer(); +#ifdef _DEBUG + EnableStressHeapHelper(); +#endif + } + + +private: + static INT32 FastCompareStringHelper(DWORD* strAChars, INT32 countA, DWORD* strBChars, INT32 countB); + + static STRINGREF* EmptyStringRefPtr; +}; + +//The first two macros are essentially the same. I just define both because +//having both can make the code more readable. +#define IS_FAST_SORT(state) (((state) == STRING_STATE_FAST_OPS)) +#define IS_SLOW_SORT(state) (((state) != STRING_STATE_FAST_OPS)) + +//This macro should be used to determine things like indexing, casing, and encoding. +#define IS_FAST_OPS_EXCEPT_SORT(state) (((state)==STRING_STATE_SPECIAL_SORT) || ((state)==STRING_STATE_FAST_OPS)) +#define IS_ASCII(state) (((state)==STRING_STATE_SPECIAL_SORT) || ((state)==STRING_STATE_FAST_OPS)) +#define IS_FAST_CASING(state) IS_ASCII(state) +#define IS_FAST_INDEX(state) IS_ASCII(state) +#define IS_STRING_STATE_UNDETERMINED(state) ((state)==STRING_STATE_UNDETERMINED) +#define HAS_HIGH_CHARS(state) ((state)==STRING_STATE_HIGH_CHARS) + +/*================================GetEmptyString================================ +**Get a reference to the empty string. If we haven't already gotten one, we +**query the String class for a pointer to the empty string that we know was +**created at startup. +** +**Args: None +**Returns: A STRINGREF to the EmptyString +**Exceptions: None +==============================================================================*/ +inline STRINGREF StringObject::GetEmptyString() { + + CONTRACTL { + THROWS; + MODE_COOPERATIVE; + GC_TRIGGERS; + } CONTRACTL_END; + STRINGREF* refptr = EmptyStringRefPtr; + + //If we've never gotten a reference to the EmptyString, we need to go get one. + if (refptr==NULL) { + refptr = InitEmptyStringRefPtr(); + } + //We've already have a reference to the EmptyString, so we can just return it. + return *refptr; +} + +inline STRINGREF* StringObject::GetEmptyStringRefPtr() { + + CONTRACTL { + THROWS; + MODE_ANY; + GC_TRIGGERS; + } CONTRACTL_END; + STRINGREF* refptr = EmptyStringRefPtr; + + //If we've never gotten a reference to the EmptyString, we need to go get one. + if (refptr==NULL) { + refptr = InitEmptyStringRefPtr(); + } + //We've already have a reference to the EmptyString, so we can just return it. + return refptr; +} + +// This is used to account for the remoting cache on RuntimeType, +// RuntimeMethodInfo, and RtFieldInfo. +class BaseObjectWithCachedData : public Object +{ +#ifdef FEATURE_REMOTING + protected: + OBJECTREF m_CachedData; +#endif //FEATURE_REMOTING +}; + +// This is the Class version of the Reflection object. +// A Class has adddition information. +// For a ReflectClassBaseObject the m_pData is a pointer to a FieldDesc array that +// contains all of the final static primitives if its defined. +// m_cnt = the number of elements defined in the m_pData FieldDesc array. -1 means +// this hasn't yet been defined. +class ReflectClassBaseObject : public BaseObjectWithCachedData +{ + friend class MscorlibBinder; + +protected: + OBJECTREF m_keepalive; + OBJECTREF m_cache; + TypeHandle m_typeHandle; +#ifdef FEATURE_APPX + UINT32 m_invocationFlags; +#endif + +#ifdef _DEBUG + void TypeCheck() + { + CONTRACTL + { + NOTHROW; + MODE_COOPERATIVE; + GC_NOTRIGGER; + SO_TOLERANT; + } + CONTRACTL_END; + + MethodTable *pMT = GetMethodTable(); + while (pMT != g_pRuntimeTypeClass && pMT != NULL) + { + pMT = pMT->GetParentMethodTable(); + } + _ASSERTE(pMT == g_pRuntimeTypeClass); + } +#endif // _DEBUG + +public: + void SetType(TypeHandle type) { + CONTRACTL + { + NOTHROW; + MODE_COOPERATIVE; + GC_NOTRIGGER; + SO_TOLERANT; + } + CONTRACTL_END; + + INDEBUG(TypeCheck()); + m_typeHandle = type; + } + + void SetKeepAlive(OBJECTREF keepalive) + { + CONTRACTL + { + NOTHROW; + MODE_COOPERATIVE; + GC_NOTRIGGER; + SO_TOLERANT; + } + CONTRACTL_END; + + INDEBUG(TypeCheck()); + SetObjectReference(&m_keepalive, keepalive, GetAppDomain()); + } + + TypeHandle GetType() { + CONTRACTL + { + NOTHROW; + MODE_COOPERATIVE; + GC_NOTRIGGER; + SO_TOLERANT; + } + CONTRACTL_END; + + INDEBUG(TypeCheck()); + return m_typeHandle; + } + +}; + +// This is the Method version of the Reflection object. +// A Method has adddition information. +// m_pMD - A pointer to the actual MethodDesc of the method. +// m_object - a field that has a reference type in it. Used only for RuntimeMethodInfoStub to keep the real type alive. +// This structure matches the structure up to the m_pMD for several different managed types. +// (RuntimeConstructorInfo, RuntimeMethodInfo, and RuntimeMethodInfoStub). These types are unrelated in the type +// system except that they all implement a particular interface. It is important that that interface is not attached to any +// type that does not sufficiently match this data structure. +class ReflectMethodObject : public BaseObjectWithCachedData +{ + friend class MscorlibBinder; + +protected: + OBJECTREF m_object; + OBJECTREF m_empty1; + OBJECTREF m_empty2; + OBJECTREF m_empty3; + OBJECTREF m_empty4; + OBJECTREF m_empty5; + OBJECTREF m_empty6; + OBJECTREF m_empty7; + MethodDesc * m_pMD; + +public: + void SetMethod(MethodDesc *pMethod) { + LIMITED_METHOD_CONTRACT; + m_pMD = pMethod; + } + + // This must only be called on instances of ReflectMethodObject that are actually RuntimeMethodInfoStub + void SetKeepAlive(OBJECTREF keepalive) + { + WRAPPER_NO_CONTRACT; + SetObjectReference(&m_object, keepalive, GetAppDomain()); + } + + MethodDesc *GetMethod() { + LIMITED_METHOD_CONTRACT; + return m_pMD; + } + +}; + +// This is the Field version of the Reflection object. +// A Method has adddition information. +// m_pFD - A pointer to the actual MethodDesc of the method. +// m_object - a field that has a reference type in it. Used only for RuntimeFieldInfoStub to keep the real type alive. +// This structure matches the structure up to the m_pFD for several different managed types. +// (RtFieldInfo and RuntimeFieldInfoStub). These types are unrelated in the type +// system except that they all implement a particular interface. It is important that that interface is not attached to any +// type that does not sufficiently match this data structure. +class ReflectFieldObject : public BaseObjectWithCachedData +{ + friend class MscorlibBinder; + +protected: + OBJECTREF m_object; + OBJECTREF m_empty1; + INT32 m_empty2; + OBJECTREF m_empty3; + OBJECTREF m_empty4; + FieldDesc * m_pFD; + +public: + void SetField(FieldDesc *pField) { + LIMITED_METHOD_CONTRACT; + m_pFD = pField; + } + + // This must only be called on instances of ReflectFieldObject that are actually RuntimeFieldInfoStub + void SetKeepAlive(OBJECTREF keepalive) + { + WRAPPER_NO_CONTRACT; + SetObjectReference(&m_object, keepalive, GetAppDomain()); + } + + FieldDesc *GetField() { + LIMITED_METHOD_CONTRACT; + return m_pFD; + } +}; + +// ReflectModuleBaseObject +// This class is the base class for managed Module. +// This class will connect the Object back to the underlying VM representation +// m_ReflectClass -- This is the real Class that was used for reflection +// This class was used to get at this object +// m_pData -- this is a generic pointer which usually points CorModule +// +class ReflectModuleBaseObject : public Object +{ + friend class MscorlibBinder; + + protected: + // READ ME: + // Modifying the order or fields of this object may require other changes to the + // classlib class definition of this object. + OBJECTREF m_runtimeType; + OBJECTREF m_runtimeAssembly; + void* m_ReflectClass; // Pointer to the ReflectClass structure + Module* m_pData; // Pointer to the Module + void* m_pGlobals; // Global values.... + void* m_pGlobalsFlds; // Global Fields.... + + protected: + ReflectModuleBaseObject() {LIMITED_METHOD_CONTRACT;} + ~ReflectModuleBaseObject() {LIMITED_METHOD_CONTRACT;} + + public: + void SetModule(Module* p) { + LIMITED_METHOD_CONTRACT; + m_pData = p; + } + Module* GetModule() { + LIMITED_METHOD_CONTRACT; + return m_pData; + } + void SetAssembly(OBJECTREF assembly) + { + WRAPPER_NO_CONTRACT; + SetObjectReference(&m_runtimeAssembly, assembly, GetAppDomain()); + } +}; + +NOINLINE ReflectModuleBaseObject* GetRuntimeModuleHelper(LPVOID __me, Module *pModule, OBJECTREF keepAlive); +#define FC_RETURN_MODULE_OBJECT(pModule, refKeepAlive) FC_INNER_RETURN(ReflectModuleBaseObject*, GetRuntimeModuleHelper(__me, pModule, refKeepAlive)) + +class SafeHandle; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<SafeHandle> SAFEHANDLE; +typedef REF<SafeHandle> SAFEHANDLEREF; +#else // USE_CHECKED_OBJECTREFS +typedef SafeHandle * SAFEHANDLE; +typedef SafeHandle * SAFEHANDLEREF; +#endif // USE_CHECKED_OBJECTREFS + +class PermissionListSetObject: public Object +{ + friend class MscorlibBinder; + +private: + OBJECTREF _firstPermSetTriple; + OBJECTREF _permSetTriples; +#ifdef FEATURE_COMPRESSEDSTACK + OBJECTREF _zoneList; + OBJECTREF _originList; +#endif // FEATURE_COMPRESSEDSTACK + +public: + BOOL IsEmpty() + { + LIMITED_METHOD_CONTRACT; + return (_firstPermSetTriple == NULL && + _permSetTriples == NULL +#ifdef FEATURE_COMPRESSEDSTACK + && _zoneList == NULL && + _originList == NULL +#endif // FEATURE_COMPRESSEDSTACK + ); + } +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<PermissionListSetObject> PERMISSIONLISTSETREF; +#else +typedef PermissionListSetObject* PERMISSIONLISTSETREF; +#endif +#ifdef FEATURE_COMPRESSEDSTACK +class CompressedStackObject: public Object +{ + friend class MscorlibBinder; + +private: + // These field are also defined in the managed representation. (CompressedStack.cs)If you + // add or change these field you must also change the managed code so that + // it matches these. This is necessary so that the object is the proper + // size. + PERMISSIONLISTSETREF m_pls; + SAFEHANDLEREF m_compressedStackHandle; + +public: + void* GetUnmanagedCompressedStack(); + BOOL IsEmptyPLS() + { + LIMITED_METHOD_CONTRACT; + return (m_pls == NULL || m_pls->IsEmpty()); + } +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<CompressedStackObject> COMPRESSEDSTACKREF; +#else +typedef CompressedStackObject* COMPRESSEDSTACKREF; +#endif +#endif // #ifdef FEATURE_COMPRESSEDSTACK + +#if defined(FEATURE_IMPERSONATION) || defined(FEATURE_COMPRESSEDSTACK) +class SecurityContextObject: public Object +{ + friend class MscorlibBinder; + +private: + + // These field are also defined in the managed representation. (SecurityContext.cs)If you + // add or change these field you must also change the managed code so that + // it matches these. This is necessary so that the object is the proper + // size. + + OBJECTREF _executionContext; +#ifdef FEATURE_IMPERSONATION + OBJECTREF _windowsIdentity; +#endif // FEATURE_IMPERSONATION +#ifdef FEATURE_COMPRESSEDSTACK + COMPRESSEDSTACKREF _compressedStack; +#endif // FEATURE_COMPRESSEDSTACK + INT32 _disableFlow; + CLR_BOOL _isNewCapture; +public: +#ifdef FEATURE_COMPRESSEDSTACK + COMPRESSEDSTACKREF GetCompressedStack() + { + LIMITED_METHOD_CONTRACT; + return _compressedStack; + } +#endif // #ifdef FEATURE_COMPRESSEDSTACK +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<SecurityContextObject> SECURITYCONTEXTREF; +#else +typedef SecurityContextObject* SECURITYCONTEXTREF; +#endif +#endif // #if defined(FEATURE_IMPERSONATION) || defined(FEATURE_COMPRESSEDSTACK) + +#ifdef FEATURE_SYNCHRONIZATIONCONTEXT_WAIT +#define SYNCCTXPROPS_REQUIRESWAITNOTIFICATION 0x1 // Keep in sync with SynchronizationContext.cs SynchronizationContextFlags +class ThreadBaseObject; +class SynchronizationContextObject: public Object +{ + friend class MscorlibBinder; +private: + // These field are also defined in the managed representation. (SecurityContext.cs)If you + // add or change these field you must also change the managed code so that + // it matches these. This is necessary so that the object is the proper + // size. + INT32 _props; +public: + BOOL IsWaitNotificationRequired() + { + LIMITED_METHOD_CONTRACT; + if ((_props & SYNCCTXPROPS_REQUIRESWAITNOTIFICATION) != 0) + return TRUE; + return FALSE; + } +}; +#endif // FEATURE_SYNCHRONIZATIONCONTEXT_WAIT + +#ifdef FEATURE_REMOTING +class CallContextRemotingDataObject : public Object +{ +private: + // These field are also defined in the managed representation. (SecurityContext.cs)If you + // add or change these field you must also change the managed code so that + // it matches these. This is necessary so that the object is the proper + // size. + OBJECTREF _logicalCallID; +public: + OBJECTREF GetLogicalCallID() + { + LIMITED_METHOD_CONTRACT; + return _logicalCallID; + } +}; + +class CallContextSecurityDataObject : public Object +{ +private: + // These field are also defined in the managed representation. (SecurityContext.cs)If you + // add or change these field you must also change the managed code so that + // it matches these. This is necessary so that the object is the proper + // size. + OBJECTREF _principal; +public: + OBJECTREF GetPrincipal() + { + LIMITED_METHOD_CONTRACT; + return _principal; + } + + void SetPrincipal(OBJECTREF ref) + { + WRAPPER_NO_CONTRACT; + SetObjectReferenceUnchecked(&_principal, ref); + } +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<CallContextSecurityDataObject> CCSECURITYDATAREF; +typedef REF<CallContextRemotingDataObject> CCREMOTINGDATAREF; +#else +typedef CallContextSecurityDataObject* CCSECURITYDATAREF; +typedef CallContextRemotingDataObject* CCREMOTINGDATAREF; +#endif + +class LogicalCallContextObject : public Object +{ + friend class MscorlibBinder; + + // These field are also defined in the managed representation. (CallContext.cs) If you + // add or change these field you must also change the managed code so that + // it matches these. This is necessary so that the object is the proper + // size. +private : + OBJECTREF m_Datastore; + CCREMOTINGDATAREF m_RemotingData; + CCSECURITYDATAREF m_SecurityData; + OBJECTREF m_HostContext; + OBJECTREF _sendHeaders; + OBJECTREF _recvHeaders; + CLR_BOOL m_IsCorrelationMgr; + +public: + CCSECURITYDATAREF GetSecurityData() + { + LIMITED_METHOD_CONTRACT; + return m_SecurityData; + } + + // This is an unmanaged equivalent of System.Runtime.Remoting.Messaging.LogicalCallContext.HasInfo + BOOL ContainsDataForSerialization() + { + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + SO_TOLERANT; + MODE_COOPERATIVE; + } + CONTRACTL_END; + return (ContainsNonSecurityDataForSerialization() || + (m_SecurityData != NULL && m_SecurityData->GetPrincipal() != NULL)); + } + + BOOL ContainsNonSecurityDataForSerialization() + { + LIMITED_METHOD_CONTRACT; + + // m_Datastore may contain 0 items even if it's non-NULL in which case it does + // not really contain any useful data for serialization and this function could + // return FALSE. However we don't waste time trying to detect this case - it will + // be reset to NULL the first time a call is made due to how LogicalCallContext's + // ISerializable implementation works. + return (m_Datastore != NULL || + (m_RemotingData != NULL && m_RemotingData->GetLogicalCallID() != NULL) || + m_HostContext != NULL); + } +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<LogicalCallContextObject> LOGICALCALLCONTEXTREF; +#else +typedef LogicalCallContextObject* LOGICALCALLCONTEXTREF; +#endif + +#endif // FEATURE_REMOTING + +#ifndef FEATURE_CORECLR +class ExecutionContextObject : public Object +{ + friend class MscorlibBinder; + + // These fields are also defined in the managed representation. (ExecutionContext.cs) If you + // add or change these fields you must also change the managed code so that + // it matches these. This is necessary so that the object is the proper + // size. +private : +#ifdef FEATURE_CAS_POLICY + OBJECTREF _hostExecutionContext; +#endif // FEATURE_CAS_POLICY + OBJECTREF _syncContext; + OBJECTREF _syncContextNoFlow; +#if defined(FEATURE_IMPERSONATION) || defined(FEATURE_COMPRESSEDSTACK) + SECURITYCONTEXTREF _securityContext; +#endif // #if defined(FEATURE_IMPERSONATION) || defined(FEATURE_COMPRESSEDSTACK) +#ifdef FEATURE_REMOTING + LOGICALCALLCONTEXTREF _logicalCallContext; + OBJECTREF _illogicalCallContext; +#endif // #ifdef FEATURE_REMOTING + INT32 _flags; + OBJECTREF _localValues; + OBJECTREF _localChangeNotifications; + +public: + OBJECTREF GetSynchronizationContext() + { + LIMITED_METHOD_CONTRACT; + return _syncContext; + } +#if defined(FEATURE_IMPERSONATION) || defined(FEATURE_COMPRESSEDSTACK) + SECURITYCONTEXTREF GetSecurityContext() + { + LIMITED_METHOD_CONTRACT; + return _securityContext; + } +#endif // #if defined(FEATURE_IMPERSONATION) || defined(FEATURE_COMPRESSEDSTACK) +#ifdef FEATURE_REMOTING + LOGICALCALLCONTEXTREF GetLogicalCallContext() + { + LIMITED_METHOD_CONTRACT; + return _logicalCallContext; + } + void SetLogicalCallContext(LOGICALCALLCONTEXTREF ref) + { + WRAPPER_NO_CONTRACT; + SetObjectReferenceUnchecked((OBJECTREF*)&_logicalCallContext, (OBJECTREF)ref); + } + OBJECTREF GetIllogicalCallContext() + { + LIMITED_METHOD_CONTRACT; + return _illogicalCallContext; + } + void SetIllogicalCallContext(OBJECTREF ref) + { + WRAPPER_NO_CONTRACT; + SetObjectReferenceUnchecked((OBJECTREF*)&_illogicalCallContext, ref); + } +#endif //#ifdef FEATURE_REMOTING +#ifdef FEATURE_COMPRESSEDSTACK + COMPRESSEDSTACKREF GetCompressedStack() + { + WRAPPER_NO_CONTRACT; + if (_securityContext != NULL) + return _securityContext->GetCompressedStack(); + return NULL; + } +#endif // #ifdef FEATURE_COMPRESSEDSTACK + +}; +#endif //FEATURE_CORECLR + + + +typedef DPTR(class CultureInfoBaseObject) PTR_CultureInfoBaseObject; + +#ifdef USE_CHECKED_OBJECTREFS +#ifdef FEATURE_SYNCHRONIZATIONCONTEXT_WAIT +typedef REF<SynchronizationContextObject> SYNCHRONIZATIONCONTEXTREF; +#endif // FEATURE_SYNCHRONIZATIONCONTEXT_WAIT +typedef REF<ExecutionContextObject> EXECUTIONCONTEXTREF; +typedef REF<CultureInfoBaseObject> CULTUREINFOBASEREF; +typedef REF<ArrayBase> ARRAYBASEREF; + +#else +#ifdef FEATURE_SYNCHRONIZATIONCONTEXT_WAIT +typedef SynchronizationContextObject* SYNCHRONIZATIONCONTEXTREF; +#endif // FEATURE_SYNCHRONIZATIONCONTEXT_WAIT +#ifndef FEATURE_CORECLR +typedef ExecutionContextObject* EXECUTIONCONTEXTREF; +#endif +typedef CultureInfoBaseObject* CULTUREINFOBASEREF; +typedef PTR_ArrayBase ARRAYBASEREF; +#endif + +// Note that the name must always be "" or "en-US". Other cases and nulls +// aren't allowed (we already checked.) +__inline bool IsCultureEnglishOrInvariant(LPCWSTR localeName) +{ + LIMITED_METHOD_CONTRACT; + if (localeName != NULL && + (localeName[0] == W('\0') || + wcscmp(localeName, W("en-US")) == 0)) + { + return true; + } + return false; + } + +class CultureInfoBaseObject : public Object +{ + friend class MscorlibBinder; + +private: + OBJECTREF compareInfo; + OBJECTREF textInfo; +#ifndef FEATURE_CORECLR + OBJECTREF regionInfo; +#endif // !FEATURE_CORECLR + OBJECTREF numInfo; + OBJECTREF dateTimeInfo; + OBJECTREF calendar; + OBJECTREF m_cultureData; +#ifndef FEATURE_CORECLR + OBJECTREF m_consoleFallbackCulture; +#endif // !FEATURE_CORECLR + STRINGREF m_name; // "real" name - en-US, de-DE_phoneb or fj-FJ + STRINGREF m_nonSortName; // name w/o sort info (de-DE for de-DE_phoneb) + STRINGREF m_sortName; // Sort only name (de-DE_phoneb, en-us for fj-fj (w/us sort) + CULTUREINFOBASEREF m_parent; +#ifndef FEATURE_COREFX_GLOBALIZATION + INT32 iDataItem; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett) + INT32 iCultureID; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett) +#endif // !FEATURE_COREFX_GLOBALIZATION +#ifdef FEATURE_LEAK_CULTURE_INFO + INT32 m_createdDomainID; +#endif // FEATURE_LEAK_CULTURE_INFO + CLR_BOOL m_isReadOnly; + CLR_BOOL m_isInherited; +#ifdef FEATURE_LEAK_CULTURE_INFO + CLR_BOOL m_isSafeCrossDomain; +#endif // FEATURE_LEAK_CULTURE_INFO + CLR_BOOL m_useUserOverride; + +public: + CULTUREINFOBASEREF GetParent() + { + LIMITED_METHOD_CONTRACT; + return m_parent; + }// GetParent + + + STRINGREF GetName() + { + LIMITED_METHOD_CONTRACT; + return m_name; + }// GetName + +#ifdef FEATURE_LEAK_CULTURE_INFO + BOOL IsSafeCrossDomain() + { + return m_isSafeCrossDomain; + }// IsSafeCrossDomain + + ADID GetCreatedDomainID() + { + return ADID(m_createdDomainID); + }// GetCreatedDomain +#endif // FEATURE_LEAK_CULTURE_INFO + +}; // class CultureInfoBaseObject + + +#ifndef FEATURE_COREFX_GLOBALIZATION +typedef DPTR(class CultureDataBaseObject) PTR_CultureDataBaseObject; +class CultureDataBaseObject : public Object +{ +public: + // offsets are for Silverlight + /* 0x000 */ STRINGREF sRealName ; // Name you passed in (ie: en-US, en, or de-DE_phoneb) + /* 0x008 */ STRINGREF sWindowsName ; // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in)) + /* 0x010 */ STRINGREF sName ; // locale name (ie: en-us, NO sort info, but could be neutral) + /* 0x012 */ STRINGREF sParent ; // Parent name (which may be a custom locale/culture) + /* 0x020 */ STRINGREF sLocalizedDisplayName ; // Localized pretty name for this locale + /* 0x028 */ STRINGREF sEnglishDisplayName ; // English pretty name for this locale + /* 0x030 */ STRINGREF sNativeDisplayName ; // Native pretty name for this locale + /* 0x038 */ STRINGREF sSpecificCulture ; // The culture name to be used in CultureInfo.CreateSpecificCulture(), en-US form if neutral, sort name if sort + /* 0x040 */ STRINGREF sISO639Language ; // ISO 639 Language Name + /* 0x048 */ STRINGREF sLocalizedLanguage ; // Localized name for this language + /* 0x050 */ STRINGREF sEnglishLanguage ; // English name for this language + /* 0x058 */ STRINGREF sNativeLanguage ; // Native name of this language + /* 0x060 */ STRINGREF sRegionName ; // (RegionInfo) + /* 0x068 */ STRINGREF sLocalizedCountry ; // localized country name + /* 0x070 */ STRINGREF sEnglishCountry ; // english country name (RegionInfo) + /* 0x078 */ STRINGREF sNativeCountry ; // native country name + /* 0x080 */ STRINGREF sISO3166CountryName ; // (RegionInfo), ie: US + /* 0x088 */ STRINGREF sPositiveSign ; // (user can override) positive sign + /* 0x090 */ STRINGREF sNegativeSign ; // (user can override) negative sign + + /* 0x098 */ PTRARRAYREF saNativeDigits ; // (user can override) native characters for digits 0-9 + /* 0x0a0 */ I4ARRAYREF waGrouping ; // (user can override) grouping of digits + + /* 0x0a8 */ STRINGREF sDecimalSeparator ; // (user can override) decimal separator + /* 0x0b0 */ STRINGREF sThousandSeparator ; // (user can override) thousands separator + /* 0x0b8 */ STRINGREF sNaN ; // Not a Number + /* 0x0c0 */ STRINGREF sPositiveInfinity ; // + Infinity + /* 0x0c8 */ STRINGREF sNegativeInfinity ; // - Infinity + /* 0x0d0 */ STRINGREF sPercent ; // Percent (%) symbol + /* 0x0d8 */ STRINGREF sPerMille ; // PerMille (U+2030) symbol + /* 0x0e0 */ STRINGREF sCurrency ; // (user can override) local monetary symbol + /* 0x0e8 */ STRINGREF sIntlMonetarySymbol ; // international monetary symbol (RegionInfo) + /* 0x0f0 */ STRINGREF sEnglishCurrency ; // English name for this currency + /* 0x0f8 */ STRINGREF sNativeCurrency ; // Native name for this currency + + /* 0x100 */ I4ARRAYREF waMonetaryGrouping ; // (user can override) monetary grouping of digits + + /* 0x108 */ STRINGREF sMonetaryDecimal ; // (user can override) monetary decimal separator + /* 0x110 */ STRINGREF sMonetaryThousand ; // (user can override) monetary thousands separator + /* 0x118 */ STRINGREF sListSeparator ; // (user can override) list separator + /* 0x120 */ STRINGREF sAM1159 ; // (user can override) AM designator + /* 0x128 */ STRINGREF sPM2359 ; // (user can override) PM designator + STRINGREF sTimeSeparator ; // Time Separator + + /* 0x130 */ PTRARRAYREF saLongTimes ; // (user can override) time format + /* 0x138 */ PTRARRAYREF saShortTimes ; // short time format + /* 0x140 */ PTRARRAYREF saDurationFormats ; // time duration format + + /* 0x148 */ I4ARRAYREF waCalendars ; // all available calendar type(s). The first one is the default calendar + + /* 0x150 */ PTRARRAYREF calendars ; // Store for specific calendar data + + /* 0x158 */ STRINGREF sTextInfo ; // Text info name to use for custom + /* 0x160 */ STRINGREF sCompareInfo ; // Compare info name (including sorting key) to use if custom + /* 0x168 */ STRINGREF sScripts ; // Typical Scripts for this locale (latn;cyrl; etc) + + // these are ordered correctly + /* ????? */ STRINGREF sAbbrevLang ; // abbreviated language name (Windows Language Name) ex: ENU + /* ????? */ STRINGREF sAbbrevCountry ; // abbreviated country name (RegionInfo) (Windows Region Name) ex: USA + /* ????? */ STRINGREF sISO639Language2 ; // 3 char ISO 639 lang name 2 ex: eng + /* ????? */ STRINGREF sISO3166CountryName2 ; // 3 char ISO 639 country name 2 2(RegionInfo) ex: USA (ISO) + /* ????? */ STRINGREF sConsoleFallbackName ; // The culture name for the console fallback UI culture + /* ????? */ STRINGREF sKeyboardsToInstall ; // Keyboard installation string. + /* ????? */ STRINGREF fontSignature ; // Font signature (16 WORDS) + +// Unused for now: /* ????? */ INT32 iCountry ; // (user can override) country code (RegionInfo) + /* 0x170 */ INT32 iGeoId ; // GeoId + /* 0x174 */ INT32 iDigitSubstitution ; // (user can override) Digit substitution 0=context, 1=none/arabic, 2=Native/national (2 seems to be unused) + /* 0x178 */ INT32 iLeadingZeros ; // (user can override) leading zeros 0 = no leading zeros, 1 = leading zeros + /* 0x17c */ INT32 iDigits ; // (user can override) number of fractional digits + /* 0x180 */ INT32 iNegativeNumber ; // (user can override) negative number format + /* 0x184 */ INT32 iNegativePercent ; // Negative Percent (0-3) + /* 0x188 */ INT32 iPositivePercent ; // Positive Percent (0-11) + /* 0x18c */ INT32 iCurrencyDigits ; // (user can override) # local monetary fractional digits + /* 0x190 */ INT32 iCurrency ; // (user can override) positive currency format + /* 0x194 */ INT32 iNegativeCurrency ; // (user can override) negative currency format + /* 0x198 */ INT32 iMeasure ; // (user can override) system of measurement 0=metric, 1=US (RegionInfo) +// Unused for now /* ????? */ INT32 iPaperSize ; // default paper size (RegionInfo) + /* 0x19c */ INT32 iFirstDayOfWeek ; // (user can override) first day of week (gregorian really) + /* 0x1a0 */ INT32 iFirstWeekOfYear ; // (user can override) first week of year (gregorian really) + + /* ????? */ INT32 iReadingLayout; // Reading Layout Data (0-3) + + // these are ordered correctly + /* ????? */ INT32 iDefaultAnsiCodePage ; // default ansi code page ID (ACP) + /* ????? */ INT32 iDefaultOemCodePage ; // default oem code page ID (OCP or OEM) + /* ????? */ INT32 iDefaultMacCodePage ; // default macintosh code page + /* ????? */ INT32 iDefaultEbcdicCodePage ; // default EBCDIC code page + /* ????? */ INT32 iLanguage ; // locale ID (0409) - NO sort information + /* ????? */ INT32 iInputLanguageHandle ; // input language handle + /* 0x1a4 */ CLR_BOOL bUseOverrides ; // use user overrides? + /* 0x1a5 */ CLR_BOOL bNeutral ; // Flags for the culture (ie: neutral or not right now) + /* ????? */ CLR_BOOL bWin32Installed ; // Flags indicate if the culture is Win32 installed + /* ????? */ CLR_BOOL bFramework ; // Flags for indicate if the culture is one of Whidbey cultures + +}; // class CultureDataBaseObject + + + +typedef DPTR(class CalendarDataBaseObject) PTR_CalendarDataBaseObject; +class CalendarDataBaseObject : public Object +{ +public: + /* 0x000 */ STRINGREF sNativeName ; // Calendar Name for the locale + + // Formats + + /* 0x008 */ PTRARRAYREF saShortDates ; // Short Data format, default first + /* 0x010 */ PTRARRAYREF saYearMonths ; // Year/Month Data format, default first + /* 0x018 */ PTRARRAYREF saLongDates ; // Long Data format, default first + /* 0x020 */ STRINGREF sMonthDay ; // Month/Day format + + // Calendar Parts Names + /* 0x028 */ PTRARRAYREF saEraNames ; // Names of Eras + /* 0x030 */ PTRARRAYREF saAbbrevEraNames ; // Abbreviated Era Names + /* 0x038 */ PTRARRAYREF saAbbrevEnglishEraNames ; // Abbreviated Era Names in English + /* 0x040 */ PTRARRAYREF saDayNames ; // Day Names, null to use locale data, starts on Sunday + /* 0x048 */ PTRARRAYREF saAbbrevDayNames ; // Abbrev Day Names, null to use locale data, starts on Sunday + /* 0x050 */ PTRARRAYREF saSuperShortDayNames ; // Super short Day of week names + /* 0x058 */ PTRARRAYREF saMonthNames ; // Month Names (13) + /* 0x060 */ PTRARRAYREF saAbbrevMonthNames ; // Abbrev Month Names (13) + /* 0x068 */ PTRARRAYREF saMonthGenitiveNames ; // Genitive Month Names (13) + /* 0x070 */ PTRARRAYREF saAbbrevMonthGenitiveNames ; // Genitive Abbrev Month Names (13) + /* 0x078 */ PTRARRAYREF saLeapYearMonthNames ; // Multiple strings for the month names in a leap year. + + // Integers at end to make marshaller happier + /* 0x080 */ INT32 iTwoDigitYearMax ; // Max 2 digit year (for Y2K bug data entry) + /* 0x084 */ INT32 iCurrentEra ; // current era # (usually 1) + + // Use overrides? + /* 0x088 */ CLR_BOOL bUseUserOverrides ; // True if we want user overrides. +}; // class CalendarDataBaseObject +#endif + + +typedef DPTR(class ThreadBaseObject) PTR_ThreadBaseObject; +class ThreadBaseObject : public Object +{ + friend class ClrDataAccess; + friend class ThreadNative; + friend class MscorlibBinder; + friend class Object; + +private: + + // These field are also defined in the managed representation. If you + // add or change these field you must also change the managed code so that + // it matches these. This is necessary so that the object is the proper + // size. The order here must match that order which the loader will choose + // when laying out the managed class. Note that the layouts are checked + // at run time, not compile time. +#ifdef FEATURE_REMOTING + OBJECTREF m_ExposedContext; +#endif +#ifdef FEATURE_CORECLR + OBJECTREF m_ExecutionContext; + OBJECTREF m_SynchronizationContext; +#else + EXECUTIONCONTEXTREF m_ExecutionContext; +#endif + OBJECTREF m_Name; + OBJECTREF m_Delegate; +#ifdef FEATURE_LEAK_CULTURE_INFO + CULTUREINFOBASEREF m_CurrentUserCulture; + CULTUREINFOBASEREF m_CurrentUICulture; +#endif +#ifdef IO_CANCELLATION_ENABLED + OBJECTREF m_CancellationSignals; +#endif + OBJECTREF m_ThreadStartArg; + + // The next field (m_InternalThread) is declared as IntPtr in the managed + // definition of Thread. The loader will sort it next. + + // m_InternalThread is always valid -- unless the thread has finalized and been + // resurrected. (The thread stopped running before it was finalized). + Thread *m_InternalThread; + INT32 m_Priority; + + //We need to cache the thread id in managed code for perf reasons. + INT32 m_ManagedThreadId; + + CLR_BOOL m_ExecutionContextBelongsToCurrentScope; +#ifdef _DEBUG + CLR_BOOL m_ForbidExecutionContextMutation; +#endif + +protected: + // the ctor and dtor can do no useful work. + ThreadBaseObject() {LIMITED_METHOD_CONTRACT;}; + ~ThreadBaseObject() {LIMITED_METHOD_CONTRACT;}; + +public: + Thread *GetInternal() + { + LIMITED_METHOD_CONTRACT; + return m_InternalThread; + } + + void SetInternal(Thread *it); + void ClearInternal(); + + INT32 GetManagedThreadId() + { + LIMITED_METHOD_CONTRACT; + return m_ManagedThreadId; + } + + void SetManagedThreadId(INT32 id) + { + LIMITED_METHOD_CONTRACT; + m_ManagedThreadId = id; + } + + OBJECTREF GetThreadStartArg() { LIMITED_METHOD_CONTRACT; return m_ThreadStartArg; } + void SetThreadStartArg(OBJECTREF newThreadStartArg) + { + WRAPPER_NO_CONTRACT; + + _ASSERTE(newThreadStartArg == NULL); + // Note: this is an unchecked assignment. We are cleaning out the ThreadStartArg field when + // a thread starts so that ADU does not cause problems + SetObjectReferenceUnchecked( (OBJECTREF *)&m_ThreadStartArg, newThreadStartArg); + + } + + OBJECTREF GetDelegate() { LIMITED_METHOD_CONTRACT; return m_Delegate; } + void SetDelegate(OBJECTREF delegate); + +#ifndef FEATURE_LEAK_CULTURE_INFO + CULTUREINFOBASEREF GetCurrentUserCulture(); + CULTUREINFOBASEREF GetCurrentUICulture(); + OBJECTREF GetManagedThreadCulture(BOOL bUICulture); + void ResetManagedThreadCulture(BOOL bUICulture); + void ResetCurrentUserCulture(); + void ResetCurrentUICulture(); +#endif + +#ifdef FEATURE_REMOTING + // These expose the remoting context (System\Remoting\Context) + OBJECTREF GetExposedContext() { LIMITED_METHOD_CONTRACT; return m_ExposedContext; } + OBJECTREF SetExposedContext(OBJECTREF newContext) + { + WRAPPER_NO_CONTRACT; + + OBJECTREF oldContext = m_ExposedContext; + + // Note: this is a very dangerous unchecked assignment. We are taking + // responsibilty here for cleaning out the ExposedContext field when + // an app domain is unloaded. + SetObjectReferenceUnchecked( (OBJECTREF *)&m_ExposedContext, newContext ); + + return oldContext; + } +#endif + +#ifdef FEATURE_LEAK_CULTURE_INFO + CULTUREINFOBASEREF GetCurrentUserCulture() + { + LIMITED_METHOD_CONTRACT; + return m_CurrentUserCulture; + } + + void ResetCurrentUserCulture() + { + WRAPPER_NO_CONTRACT; + ClearObjectReference((OBJECTREF *)&m_CurrentUserCulture); + } + + CULTUREINFOBASEREF GetCurrentUICulture() + { + LIMITED_METHOD_CONTRACT; + return m_CurrentUICulture; + } + + void ResetCurrentUICulture() + { + WRAPPER_NO_CONTRACT; + ClearObjectReference((OBJECTREF *)&m_CurrentUICulture); + } +#endif // FEATURE_LEAK_CULTURE_INFO + +#ifndef FEATURE_CORECLR + OBJECTREF GetSynchronizationContext() + { + LIMITED_METHOD_CONTRACT; + if (m_ExecutionContext != NULL) + return m_ExecutionContext->GetSynchronizationContext(); + return NULL; + } + OBJECTREF GetExecutionContext() + { + LIMITED_METHOD_CONTRACT; + return (OBJECTREF)m_ExecutionContext; + } + void SetExecutionContext(OBJECTREF ref) + { + LIMITED_METHOD_CONTRACT; + SetObjectReferenceUnchecked((OBJECTREF*)&m_ExecutionContext, ref); + } +#endif //!FEATURE_CORECLR +#ifdef FEATURE_COMPRESSEDSTACK + COMPRESSEDSTACKREF GetCompressedStack() + { + WRAPPER_NO_CONTRACT; + if (m_ExecutionContext != NULL) + return m_ExecutionContext->GetCompressedStack(); + return NULL; + } +#endif // #ifdef FEATURE_COMPRESSEDSTACK + // SetDelegate is our "constructor" for the pathway where the exposed object is + // created first. InitExisting is our "constructor" for the pathway where an + // existing physical thread is later exposed. + void InitExisting(); + + void ResetCulture() + { + LIMITED_METHOD_CONTRACT; + ResetCurrentUserCulture(); + ResetCurrentUICulture(); + } + + void ResetName() + { + LIMITED_METHOD_CONTRACT; + m_Name = NULL; + } + + void SetPriority(INT32 priority) + { + LIMITED_METHOD_CONTRACT; + m_Priority = priority; + } + + INT32 GetPriority() const + { + LIMITED_METHOD_CONTRACT; + return m_Priority; + } +}; + +// MarshalByRefObjectBaseObject +// This class is the base class for MarshalByRefObject +// +class MarshalByRefObjectBaseObject : public Object +{ +#ifdef FEATURE_REMOTING + friend class MscorlibBinder; + + public: + static int GetOffsetOfServerIdentity() { LIMITED_METHOD_CONTRACT; return offsetof(MarshalByRefObjectBaseObject, m_ServerIdentity); } + + protected: + // READ ME: + // Modifying the order or fields of this object may require other changes to the + // classlib class definition of this object. + OBJECTREF m_ServerIdentity; + + protected: + MarshalByRefObjectBaseObject() {LIMITED_METHOD_CONTRACT;} + ~MarshalByRefObjectBaseObject() {LIMITED_METHOD_CONTRACT;} +#endif +}; + + +// ContextBaseObject +// This class is the base class for Contexts +// +class ContextBaseObject : public Object +{ + friend class Context; + friend class MscorlibBinder; + + private: + // READ ME: + // Modifying the order or fields of this object may require other changes to the + // classlib class definition of this object. + + OBJECTREF m_ctxProps; // array of name-value pairs of properties + OBJECTREF m_dphCtx; // dynamic property holder + OBJECTREF m_localDataStore; // context local store + OBJECTREF m_serverContextChain; // server context sink chain + OBJECTREF m_clientContextChain; // client context sink chain + OBJECTREF m_exposedAppDomain; //appDomain ?? + PTRARRAYREF m_ctxStatics; // holder for context relative statics + + Context* m_internalContext; // Pointer to the VM context + + INT32 _ctxID; + INT32 _ctxFlags; + INT32 _numCtxProps; // current count of properties + + INT32 _ctxStaticsCurrentBucket; + INT32 _ctxStaticsFreeIndex; + + protected: + ContextBaseObject() { LIMITED_METHOD_CONTRACT; } + ~ContextBaseObject() { LIMITED_METHOD_CONTRACT; } + + public: + + void SetInternalContext(Context* pCtx) + { + LIMITED_METHOD_CONTRACT; + // either transitioning from NULL to non-NULL or vice versa. + // But not setting NULL to NULL or non-NULL to non-NULL. + _ASSERTE((m_internalContext == NULL) != (pCtx == NULL)); + m_internalContext = pCtx; + } + + Context* GetInternalContext() + { + LIMITED_METHOD_CONTRACT; + return m_internalContext; + } + + OBJECTREF GetExposedDomain() { return m_exposedAppDomain; } + OBJECTREF SetExposedDomain(OBJECTREF newDomain) + { + LIMITED_METHOD_CONTRACT; + OBJECTREF oldDomain = m_exposedAppDomain; + SetObjectReference( (OBJECTREF *)&m_exposedAppDomain, newDomain, GetAppDomain() ); + return oldDomain; + } + + PTRARRAYREF GetContextStaticsHolder() + { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + // The code that needs this should have faulted it in by now! + _ASSERTE(m_ctxStatics != NULL); + + return m_ctxStatics; + } +}; + +typedef DPTR(ContextBaseObject) PTR_ContextBaseObject; + +// AppDomainBaseObject +// This class is the base class for application domains +// +class AppDomainBaseObject : public MarshalByRefObjectBaseObject +{ + friend class AppDomain; + friend class MscorlibBinder; + + protected: + // READ ME: + // Modifying the order or fields of this object may require other changes to the + // classlib class definition of this object. + OBJECTREF m_pDomainManager; // AppDomainManager for host settings. + OBJECTREF m_LocalStore; + OBJECTREF m_FusionTable; + OBJECTREF m_pSecurityIdentity; // Evidence associated with this domain + OBJECTREF m_pPolicies; // Array of context policies associated with this domain + OBJECTREF m_pAssemblyEventHandler; // Delegate for 'loading assembly' event + OBJECTREF m_pTypeEventHandler; // Delegate for 'resolve type' event + OBJECTREF m_pResourceEventHandler; // Delegate for 'resolve resource' event + OBJECTREF m_pAsmResolveEventHandler; // Delegate for 'resolve assembly' event +#ifdef FEATURE_REFLECTION_ONLY_LOAD + OBJECTREF m_pReflectionAsmResolveEventHandler; //Delegate for 'reflection resolve assembly' event +#endif +#ifdef FEATURE_REMOTING + OBJECTREF m_pDefaultContext; // Default managed context for this AD. +#endif +#ifdef FEATURE_CLICKONCE + OBJECTREF m_pActivationContext; // ClickOnce ActivationContext. + OBJECTREF m_pApplicationIdentity; // App ApplicationIdentity. +#endif + OBJECTREF m_pApplicationTrust; // App ApplicationTrust. +#ifdef FEATURE_IMPERSONATION + OBJECTREF m_pDefaultPrincipal; // Lazily computed default principle object used by threads +#endif // FEATURE_IMPERSONATION +#ifdef FEATURE_REMOTING + OBJECTREF m_pURITable; // Identity table for remoting +#endif + OBJECTREF m_pProcessExitEventHandler; // Delegate for 'process exit' event. Only used in Default appdomain. + OBJECTREF m_pDomainUnloadEventHandler; // Delegate for 'about to unload domain' event + OBJECTREF m_pUnhandledExceptionEventHandler; // Delegate for 'unhandled exception' event +#ifdef FEATURE_APTCA + OBJECTREF m_aptcaVisibleAssemblies; // array of conditional APTCA assembly names that should be APTCA visible +#endif + + OBJECTREF m_compatFlags; + +#ifdef FEATURE_EXCEPTION_NOTIFICATIONS + OBJECTREF m_pFirstChanceExceptionHandler; // Delegate for 'FirstChance Exception' event +#endif // FEATURE_EXCEPTION_NOTIFICATIONS + + AppDomain* m_pDomain; // Pointer to the BaseDomain Structure +#ifdef FEATURE_CAS_POLICY + INT32 m_iPrincipalPolicy; // Type of principal to create by default +#endif + CLR_BOOL m_bHasSetPolicy; // SetDomainPolicy has been called for this domain + CLR_BOOL m_bIsFastFullTrustDomain; // We know for sure that this is a homogeneous full trust domain. + CLR_BOOL m_compatFlagsInitialized; + + protected: + AppDomainBaseObject() { LIMITED_METHOD_CONTRACT; } + ~AppDomainBaseObject() { LIMITED_METHOD_CONTRACT; } + + public: + + void SetDomain(AppDomain* p) + { + LIMITED_METHOD_CONTRACT; + m_pDomain = p; + } + AppDomain* GetDomain() + { + LIMITED_METHOD_CONTRACT; + return m_pDomain; + } + + OBJECTREF GetSecurityIdentity() + { + LIMITED_METHOD_CONTRACT; + return m_pSecurityIdentity; + } + + OBJECTREF GetAppDomainManager() + { + LIMITED_METHOD_CONTRACT; + return m_pDomainManager; + } + + OBJECTREF GetApplicationTrust() + { + LIMITED_METHOD_CONTRACT; + return m_pApplicationTrust; + } + + BOOL GetIsFastFullTrustDomain() + { + LIMITED_METHOD_CONTRACT; + return !!m_bIsFastFullTrustDomain; + } + +#ifdef FEATURE_APTCA + OBJECTREF GetPartialTrustVisibleAssemblies() + { + LIMITED_METHOD_CONTRACT + return m_aptcaVisibleAssemblies; + } +#endif // FEATURE_APTCA + + // Ref needs to be a PTRARRAYREF + void SetPolicies(OBJECTREF ref) + { + WRAPPER_NO_CONTRACT; + SetObjectReference(&m_pPolicies, ref, m_pDomain ); + } +#ifdef FEATURE_REMOTING + void SetDefaultContext(OBJECTREF ref) + { + WRAPPER_NO_CONTRACT; + SetObjectReference(&m_pDefaultContext,ref,m_pDomain); + } +#endif + BOOL HasSetPolicy() + { + LIMITED_METHOD_CONTRACT; + return m_bHasSetPolicy; + } + +#ifdef FEATURE_CLICKONCE + BOOL HasActivationContext() + { + LIMITED_METHOD_CONTRACT; + return m_pActivationContext != NULL; + } +#endif // FEATURE_CLICKONCE + +#ifdef FEATURE_EXCEPTION_NOTIFICATIONS + // Returns the reference to the delegate of the first chance exception notification handler + OBJECTREF GetFirstChanceExceptionNotificationHandler() + { + LIMITED_METHOD_CONTRACT; + + return m_pFirstChanceExceptionHandler; + } +#endif // FEATURE_EXCEPTION_NOTIFICATIONS +}; + +#ifndef FEATURE_CORECLR +// The managed definition of AppDomainSortingSetupInfo is in BCL\System\Globalization\AppDomainSortingSetupInfo.cs +class AppDomainSortingSetupInfoObject : public Object +{ + friend class MscorlibBinder; + + protected: + INT_PTR m_pfnIsNLSDefinedString; + INT_PTR m_pfnCompareStringEx; + INT_PTR m_pfnLCMapStringEx; + INT_PTR m_pfnFindNLSStringEx; + INT_PTR m_pfnCompareStringOrdinal; + INT_PTR m_pfnGetNLSVersionEx; + INT_PTR m_pfnFindStringOrdinal; + CLR_BOOL m_useV2LegacySorting; + CLR_BOOL m_useV4LegacySorting; + + protected: + AppDomainSortingSetupInfoObject() { LIMITED_METHOD_CONTRACT; } + ~AppDomainSortingSetupInfoObject() { LIMITED_METHOD_CONTRACT; } + + public: + CLR_BOOL UseV2LegacySorting() { LIMITED_METHOD_CONTRACT; return m_useV2LegacySorting; } + CLR_BOOL UseV4LegacySorting() { LIMITED_METHOD_CONTRACT; return m_useV4LegacySorting; } + + INT_PTR GetPFNIsNLSDefinedString() { LIMITED_METHOD_CONTRACT; return m_pfnIsNLSDefinedString; } + INT_PTR GetPFNCompareStringEx() { LIMITED_METHOD_CONTRACT; return m_pfnCompareStringEx; } + INT_PTR GetPFNLCMapStringEx() { LIMITED_METHOD_CONTRACT; return m_pfnLCMapStringEx; } + INT_PTR GetPFNFindNLSStringEx() { LIMITED_METHOD_CONTRACT; return m_pfnFindNLSStringEx; } + INT_PTR GetPFNCompareStringOrdinal() { LIMITED_METHOD_CONTRACT; return m_pfnCompareStringOrdinal; } + INT_PTR GetPFNGetNLSVersionEx() { LIMITED_METHOD_CONTRACT; return m_pfnGetNLSVersionEx; } + INT_PTR GetPFNFindStringOrdinal() { LIMITED_METHOD_CONTRACT; return m_pfnFindStringOrdinal; } +}; +typedef DPTR(AppDomainSortingSetupInfoObject) PTR_AppDomainSortingSetupInfoObject; +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<AppDomainSortingSetupInfoObject> APPDOMAINSORTINGSETUPINFOREF; +#else +typedef AppDomainSortingSetupInfoObject* APPDOMAINSORTINGSETUPINFOREF; +#endif // USE_CHECKED_OBJECTREFS +#endif // FEATURE_CORECLR + +// The managed definition of AppDomainSetup is in BCL\System\AppDomainSetup.cs +class AppDomainSetupObject : public Object +{ + friend class MscorlibBinder; + + protected: + PTRARRAYREF m_Entries; + STRINGREF m_AppBase; + OBJECTREF m_AppDomainInitializer; + PTRARRAYREF m_AppDomainInitializerArguments; +#ifdef FEATURE_CLICKONCE + OBJECTREF m_ActivationArguments; +#endif // FEATURE_CLICKONCE + STRINGREF m_ApplicationTrust; + I1ARRAYREF m_ConfigurationBytes; + STRINGREF m_AppDomainManagerAssembly; + STRINGREF m_AppDomainManagerType; +#if FEATURE_APTCA + PTRARRAYREF m_AptcaVisibleAssemblies; +#endif + OBJECTREF m_CompatFlags; + STRINGREF m_TargetFrameworkName; +#ifndef FEATURE_CORECLR + APPDOMAINSORTINGSETUPINFOREF m_AppDomainSortingSetupInfo; +#endif // FEATURE_CORECLR + INT32 m_LoaderOptimization; +#ifdef FEATURE_COMINTEROP + CLR_BOOL m_DisableInterfaceCache; +#endif // FEATURE_COMINTEROP + CLR_BOOL m_CheckedForTargetFrameworkName; +#ifdef FEATURE_RANDOMIZED_STRING_HASHING + CLR_BOOL m_UseRandomizedStringHashing; +#endif + + + protected: + AppDomainSetupObject() { LIMITED_METHOD_CONTRACT; } + ~AppDomainSetupObject() { LIMITED_METHOD_CONTRACT; } + + public: +#ifndef FEATURE_CORECLR + APPDOMAINSORTINGSETUPINFOREF GetAppDomainSortingSetupInfo() { LIMITED_METHOD_CONTRACT; return m_AppDomainSortingSetupInfo; } +#endif // FEATURE_CORECLR +#ifdef FEATURE_RANDOMIZED_STRING_HASHING + BOOL UseRandomizedStringHashing() { LIMITED_METHOD_CONTRACT; return (BOOL) m_UseRandomizedStringHashing; } +#endif // FEATURE_RANDOMIZED_STRING_HASHING +}; +typedef DPTR(AppDomainSetupObject) PTR_AppDomainSetupObject; +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<AppDomainSetupObject> APPDOMAINSETUPREF; +#else +typedef AppDomainSetupObject* APPDOMAINSETUPREF; +#endif + +// AssemblyBaseObject +// This class is the base class for assemblies +// +class AssemblyBaseObject : public Object +{ + friend class Assembly; + friend class MscorlibBinder; + + protected: + // READ ME: + // Modifying the order or fields of this object may require other changes to the + // classlib class definition of this object. + OBJECTREF m_pModuleEventHandler; // Delegate for 'resolve module' event + STRINGREF m_fullname; // Slot for storing assemblies fullname + OBJECTREF m_pSyncRoot; // Pointer to loader allocator to keep collectible types alive, and to serve as the syncroot for assembly building in ref.emit + DomainAssembly* m_pAssembly; // Pointer to the Assembly Structure +#ifdef FEATURE_APPX + UINT32 m_flags; +#endif + + protected: + AssemblyBaseObject() { LIMITED_METHOD_CONTRACT; } + ~AssemblyBaseObject() { LIMITED_METHOD_CONTRACT; } + + public: + + void SetAssembly(DomainAssembly* p) + { + LIMITED_METHOD_CONTRACT; + m_pAssembly = p; + } + + DomainAssembly* GetDomainAssembly() + { + LIMITED_METHOD_CONTRACT; + return m_pAssembly; + } + + Assembly* GetAssembly(); + + void SetSyncRoot(OBJECTREF pSyncRoot) + { + WRAPPER_NO_CONTRACT; + SetObjectReferenceUnchecked(&m_pSyncRoot, pSyncRoot); + } +}; +NOINLINE AssemblyBaseObject* GetRuntimeAssemblyHelper(LPVOID __me, DomainAssembly *pAssembly, OBJECTREF keepAlive); +#define FC_RETURN_ASSEMBLY_OBJECT(pAssembly, refKeepAlive) FC_INNER_RETURN(AssemblyBaseObject*, GetRuntimeAssemblyHelper(__me, pAssembly, refKeepAlive)) + +// AssemblyNameBaseObject +// This class is the base class for assembly names +// +class AssemblyNameBaseObject : public Object +{ + friend class AssemblyNative; + friend class AppDomainNative; + friend class MscorlibBinder; + + protected: + // READ ME: + // Modifying the order or fields of this object may require other changes to the + // classlib class definition of this object. + + OBJECTREF m_pSimpleName; + U1ARRAYREF m_pPublicKey; + U1ARRAYREF m_pPublicKeyToken; + OBJECTREF m_pCultureInfo; + OBJECTREF m_pCodeBase; + OBJECTREF m_pVersion; + OBJECTREF m_StrongNameKeyPair; + OBJECTREF m_siInfo; + U1ARRAYREF m_HashForControl; + DWORD m_HashAlgorithm; + DWORD m_HashAlgorithmForControl; + DWORD m_VersionCompatibility; + DWORD m_Flags; + + protected: + AssemblyNameBaseObject() { LIMITED_METHOD_CONTRACT; } + ~AssemblyNameBaseObject() { LIMITED_METHOD_CONTRACT; } + + public: + OBJECTREF GetSimpleName() { LIMITED_METHOD_CONTRACT; return m_pSimpleName; } + U1ARRAYREF GetPublicKey() { LIMITED_METHOD_CONTRACT; return m_pPublicKey; } + U1ARRAYREF GetPublicKeyToken() { LIMITED_METHOD_CONTRACT; return m_pPublicKeyToken; } + OBJECTREF GetStrongNameKeyPair() { LIMITED_METHOD_CONTRACT; return m_StrongNameKeyPair; } + OBJECTREF GetCultureInfo() { LIMITED_METHOD_CONTRACT; return m_pCultureInfo; } + OBJECTREF GetAssemblyCodeBase() { LIMITED_METHOD_CONTRACT; return m_pCodeBase; } + OBJECTREF GetVersion() { LIMITED_METHOD_CONTRACT; return m_pVersion; } + DWORD GetAssemblyHashAlgorithm() { LIMITED_METHOD_CONTRACT; return m_HashAlgorithm; } + DWORD GetFlags() { LIMITED_METHOD_CONTRACT; return m_Flags; } + U1ARRAYREF GetHashForControl() { LIMITED_METHOD_CONTRACT; return m_HashForControl;} + DWORD GetHashAlgorithmForControl() { LIMITED_METHOD_CONTRACT; return m_HashAlgorithmForControl; } +}; + +// VersionBaseObject +// This class is the base class for versions +// +class VersionBaseObject : public Object +{ + friend class MscorlibBinder; + + protected: + // READ ME: + // Modifying the order or fields of this object may require other changes to the + // classlib class definition of this object. + + int m_Major; + int m_Minor; + int m_Build; + int m_Revision; + + VersionBaseObject() {LIMITED_METHOD_CONTRACT;} + ~VersionBaseObject() {LIMITED_METHOD_CONTRACT;} + + public: + int GetMajor() { LIMITED_METHOD_CONTRACT; return m_Major; } + int GetMinor() { LIMITED_METHOD_CONTRACT; return m_Minor; } + int GetBuild() { LIMITED_METHOD_CONTRACT; return m_Build; } + int GetRevision() { LIMITED_METHOD_CONTRACT; return m_Revision; } +}; + +// FrameSecurityDescriptorBaseObject +// This class is the base class for the frame security descriptor +// + +class FrameSecurityDescriptorBaseObject : public Object +{ + friend class MscorlibBinder; + + protected: + // READ ME: + // Modifying the order or fields of this object may require other changes to the + // classlib class definition of this object. + + OBJECTREF m_assertions; // imperative + OBJECTREF m_denials; // imperative + OBJECTREF m_restriction; // imperative + OBJECTREF m_DeclarativeAssertions; + OBJECTREF m_DeclarativeDenials; + OBJECTREF m_DeclarativeRestrictions; +#ifndef FEATURE_PAL + SAFEHANDLEREF m_callerToken; // the thread token (or process token if there was no thread token) when a call to Impersonate was made ("previous" token) + SAFEHANDLEREF m_impToken; // the thread token after a call to Impersonate is made (the "current" impersonation) +#endif // !FEATURE_PAL + CLR_BOOL m_assertFT; + CLR_BOOL m_assertAllPossible; + CLR_BOOL m_declSecComputed; + + + + protected: + FrameSecurityDescriptorBaseObject() {LIMITED_METHOD_CONTRACT;} + ~FrameSecurityDescriptorBaseObject() {LIMITED_METHOD_CONTRACT;} + + public: + + INT32 GetOverridesCount() + { + LIMITED_METHOD_CONTRACT; + INT32 ret =0; + if (m_restriction != NULL) + ret++; + if (m_denials != NULL) + ret++; + if (m_DeclarativeDenials != NULL) + ret++; + if (m_DeclarativeRestrictions != NULL) + ret++; + return ret; + } + + INT32 GetAssertCount() + { + LIMITED_METHOD_CONTRACT; + INT32 ret =0; + if (m_assertions != NULL || m_DeclarativeAssertions != NULL || HasAssertAllPossible()) + ret++; + return ret; + } + + BOOL HasAssertFT() + { + LIMITED_METHOD_CONTRACT; + return m_assertFT; + } + + BOOL IsDeclSecComputed() + { + LIMITED_METHOD_CONTRACT; + return m_declSecComputed; + } + + BOOL HasAssertAllPossible() + { + LIMITED_METHOD_CONTRACT; + return m_assertAllPossible; + } + + OBJECTREF GetImperativeAssertions() + { + LIMITED_METHOD_CONTRACT; + return m_assertions; + } + OBJECTREF GetDeclarativeAssertions() + { + LIMITED_METHOD_CONTRACT; + return m_DeclarativeAssertions; + } + OBJECTREF GetImperativeDenials() + { + LIMITED_METHOD_CONTRACT; + return m_denials; + } + OBJECTREF GetDeclarativeDenials() + { + LIMITED_METHOD_CONTRACT; + return m_DeclarativeDenials; + } + OBJECTREF GetImperativeRestrictions() + { + LIMITED_METHOD_CONTRACT; + return m_restriction; + } + OBJECTREF GetDeclarativeRestrictions() + { + LIMITED_METHOD_CONTRACT; + return m_DeclarativeRestrictions; + } + void SetImperativeAssertions(OBJECTREF assertRef) + { + LIMITED_METHOD_CONTRACT; + SetObjectReference(&m_assertions, assertRef, this->GetAppDomain()); + } + void SetDeclarativeAssertions(OBJECTREF assertRef) + { + LIMITED_METHOD_CONTRACT; + SetObjectReference(&m_DeclarativeAssertions, assertRef, this->GetAppDomain()); + } + void SetImperativeDenials(OBJECTREF denialRef) + { + LIMITED_METHOD_CONTRACT; + SetObjectReference(&m_denials, denialRef, this->GetAppDomain()); + } + + void SetDeclarativeDenials(OBJECTREF denialRef) + { + LIMITED_METHOD_CONTRACT; + SetObjectReference(&m_DeclarativeDenials, denialRef, this->GetAppDomain()); + } + + void SetImperativeRestrictions(OBJECTREF restrictRef) + { + LIMITED_METHOD_CONTRACT; + SetObjectReference(&m_restriction, restrictRef, this->GetAppDomain()); + } + + void SetDeclarativeRestrictions(OBJECTREF restrictRef) + { + LIMITED_METHOD_CONTRACT; + SetObjectReference(&m_DeclarativeRestrictions, restrictRef, this->GetAppDomain()); + } + void SetAssertAllPossible(BOOL assertAllPossible) + { + LIMITED_METHOD_CONTRACT; + m_assertAllPossible = !!assertAllPossible; + } + + void SetAssertFT(BOOL assertFT) + { + LIMITED_METHOD_CONTRACT; + m_assertFT = !!assertFT; + } + void SetDeclSecComputed(BOOL declSec) + { + LIMITED_METHOD_CONTRACT; + m_declSecComputed = !!declSec; + } + LPVOID GetCallerToken(); + LPVOID GetImpersonationToken(); +}; + +#ifdef FEATURE_COMPRESSEDSTACK +class FrameSecurityDescriptorWithResolverBaseObject : public FrameSecurityDescriptorBaseObject +{ +public: + OBJECTREF m_resolver; + +public: + void SetDynamicMethodResolver(OBJECTREF resolver) + { + LIMITED_METHOD_CONTRACT; + SetObjectReference(&m_resolver, resolver, this->GetAppDomain()); + } +}; +#endif // FEATURE_COMPRESSEDSTACK + +class WeakReferenceObject : public Object +{ +public: + Volatile<OBJECTHANDLE> m_Handle; +}; + +#ifdef USE_CHECKED_OBJECTREFS + +typedef REF<ReflectModuleBaseObject> REFLECTMODULEBASEREF; + +typedef REF<ReflectClassBaseObject> REFLECTCLASSBASEREF; + +typedef REF<ReflectMethodObject> REFLECTMETHODREF; + +typedef REF<ReflectFieldObject> REFLECTFIELDREF; + +typedef REF<ThreadBaseObject> THREADBASEREF; + +typedef REF<AppDomainBaseObject> APPDOMAINREF; + +typedef REF<MarshalByRefObjectBaseObject> MARSHALBYREFOBJECTBASEREF; + +typedef REF<ContextBaseObject> CONTEXTBASEREF; + +typedef REF<AssemblyBaseObject> ASSEMBLYREF; + +typedef REF<AssemblyNameBaseObject> ASSEMBLYNAMEREF; + +typedef REF<VersionBaseObject> VERSIONREF; + +typedef REF<FrameSecurityDescriptorBaseObject> FRAMESECDESCREF; + +#ifdef FEATURE_COMPRESSEDSTACK +typedef REF<FrameSecurityDescriptorWithResolverBaseObject> FRAMESECDESWITHRESOLVERCREF; +#endif // FEATURE_COMPRESSEDSTACK + +typedef REF<WeakReferenceObject> WEAKREFERENCEREF; + +inline ARG_SLOT ObjToArgSlot(OBJECTREF objRef) +{ + LIMITED_METHOD_CONTRACT; + LPVOID v; + v = OBJECTREFToObject(objRef); + return (ARG_SLOT)(SIZE_T)v; +} + +inline OBJECTREF ArgSlotToObj(ARG_SLOT i) +{ + LIMITED_METHOD_CONTRACT; + LPVOID v; + v = (LPVOID)(SIZE_T)i; + return ObjectToOBJECTREF ((Object*)v); +} + +inline ARG_SLOT StringToArgSlot(STRINGREF sr) +{ + LIMITED_METHOD_CONTRACT; + LPVOID v; + v = OBJECTREFToObject(sr); + return (ARG_SLOT)(SIZE_T)v; +} + +inline STRINGREF ArgSlotToString(ARG_SLOT s) +{ + LIMITED_METHOD_CONTRACT; + LPVOID v; + v = (LPVOID)(SIZE_T)s; + return ObjectToSTRINGREF ((StringObject*)v); +} + +#else // USE_CHECKED_OBJECTREFS + +typedef PTR_ReflectModuleBaseObject REFLECTMODULEBASEREF; +typedef PTR_ReflectClassBaseObject REFLECTCLASSBASEREF; +typedef PTR_ReflectMethodObject REFLECTMETHODREF; +typedef PTR_ReflectFieldObject REFLECTFIELDREF; +typedef PTR_ThreadBaseObject THREADBASEREF; +typedef PTR_AppDomainBaseObject APPDOMAINREF; +typedef PTR_AssemblyBaseObject ASSEMBLYREF; +typedef PTR_AssemblyNameBaseObject ASSEMBLYNAMEREF; +typedef PTR_ContextBaseObject CONTEXTBASEREF; + +#ifndef DACCESS_COMPILE +typedef MarshalByRefObjectBaseObject* MARSHALBYREFOBJECTBASEREF; +typedef VersionBaseObject* VERSIONREF; +typedef FrameSecurityDescriptorBaseObject* FRAMESECDESCREF; + +#ifdef FEATURE_COMPRESSEDSTACK +typedef FrameSecurityDescriptorWithResolverBaseObject* FRAMESECDESWITHRESOLVERCREF; +#endif // FEATURE_COMPRESSEDSTACK + +typedef WeakReferenceObject* WEAKREFERENCEREF; +#endif // #ifndef DACCESS_COMPILE + +#define ObjToArgSlot(objref) ((ARG_SLOT)(SIZE_T)(objref)) +#define ArgSlotToObj(s) ((OBJECTREF)(SIZE_T)(s)) + +#define StringToArgSlot(objref) ((ARG_SLOT)(SIZE_T)(objref)) +#define ArgSlotToString(s) ((STRINGREF)(SIZE_T)(s)) + +#endif //USE_CHECKED_OBJECTREFS + +#define PtrToArgSlot(ptr) ((ARG_SLOT)(SIZE_T)(ptr)) +#define ArgSlotToPtr(s) ((LPVOID)(SIZE_T)(s)) + +#define BoolToArgSlot(b) ((ARG_SLOT)(CLR_BOOL)(!!(b))) +#define ArgSlotToBool(s) ((BOOL)(s)) + +STRINGREF AllocateString(SString sstr); +CHARARRAYREF AllocateCharArray(DWORD dwArrayLength); + + +class TransparentProxyObject : public Object +{ + friend class MscorlibBinder; + friend class CheckAsmOffsets; + +public: + MethodTable * GetMethodTableBeingProxied() + { + LIMITED_METHOD_CONTRACT; + return _pMT; + } + void SetMethodTableBeingProxied(MethodTable * pMT) + { + LIMITED_METHOD_CONTRACT; + _pMT = pMT; + } + + MethodTable * GetInterfaceMethodTable() + { + LIMITED_METHOD_CONTRACT; + return _pInterfaceMT; + } + void SetInterfaceMethodTable(MethodTable * pInterfaceMT) + { + LIMITED_METHOD_CONTRACT; + _pInterfaceMT = pInterfaceMT; + } + + void * GetStub() + { + LIMITED_METHOD_CONTRACT; + return _stub; + } + void SetStub(void * pStub) + { + LIMITED_METHOD_CONTRACT; + _stub = pStub; + } + + OBJECTREF GetStubData() + { + LIMITED_METHOD_CONTRACT; + return _stubData; + } + void SetStubData(OBJECTREF stubData) + { + LIMITED_METHOD_CONTRACT; + SetObjectReference(&_stubData, stubData, GetAppDomain()); + } + + OBJECTREF GetRealProxy() + { + LIMITED_METHOD_CONTRACT; + return _rp; + } + void SetRealProxy(OBJECTREF realProxy) + { + LIMITED_METHOD_CONTRACT; + SetObjectReference(&_rp, realProxy, GetAppDomain()); + } + + static int GetOffsetOfRP() { LIMITED_METHOD_CONTRACT; return offsetof(TransparentProxyObject, _rp); } + +protected: + TransparentProxyObject() + {LIMITED_METHOD_CONTRACT;}; // don't instantiate this class directly + ~TransparentProxyObject(){LIMITED_METHOD_CONTRACT;}; + +private: + OBJECTREF _rp; + OBJECTREF _stubData; + MethodTable* _pMT; + MethodTable* _pInterfaceMT; + void* _stub; +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<TransparentProxyObject> TRANSPARENTPROXYREF; +#else +typedef TransparentProxyObject* TRANSPARENTPROXYREF; +#endif + + +class RealProxyObject : public Object +{ + friend class MscorlibBinder; + +public: + DWORD GetOptFlags() + { + LIMITED_METHOD_CONTRACT; + return _optFlags; + } + VOID SetOptFlags(DWORD flags) + { + LIMITED_METHOD_CONTRACT; + _optFlags = flags; + } + + DWORD GetDomainID() + { + LIMITED_METHOD_CONTRACT; + return _domainID; + } + + TRANSPARENTPROXYREF GetTransparentProxy() + { + LIMITED_METHOD_CONTRACT; + return (TRANSPARENTPROXYREF&)_tp; + } + void SetTransparentProxy(TRANSPARENTPROXYREF tp) + { + LIMITED_METHOD_CONTRACT; + SetObjectReference(&_tp, (OBJECTREF)tp, GetAppDomain()); + } + + static int GetOffsetOfIdentity() { LIMITED_METHOD_CONTRACT; return offsetof(RealProxyObject, _identity); } + static int GetOffsetOfServerObject() { LIMITED_METHOD_CONTRACT; return offsetof(RealProxyObject, _serverObject); } + static int GetOffsetOfServerIdentity() { LIMITED_METHOD_CONTRACT; return offsetof(RealProxyObject, _srvIdentity); } + +protected: + RealProxyObject() + { + LIMITED_METHOD_CONTRACT; + }; // don't instantiate this class directly + ~RealProxyObject(){ LIMITED_METHOD_CONTRACT; }; + +private: + OBJECTREF _tp; + OBJECTREF _identity; + OBJECTREF _serverObject; + DWORD _flags; + DWORD _optFlags; + DWORD _domainID; + OBJECTHANDLE _srvIdentity; +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<RealProxyObject> REALPROXYREF; +#else +typedef RealProxyObject* REALPROXYREF; +#endif + + +#ifdef FEATURE_COMINTEROP + +//------------------------------------------------------------- +// class ComObject, Exposed class __ComObject +// +// +//------------------------------------------------------------- +class ComObject : public MarshalByRefObjectBaseObject +{ + friend class MscorlibBinder; + +protected: + + ComObject() + {LIMITED_METHOD_CONTRACT;}; // don't instantiate this class directly + ~ComObject(){LIMITED_METHOD_CONTRACT;}; + +public: + OBJECTREF m_ObjectToDataMap; + + //-------------------------------------------------------------------- + // SupportsInterface + static BOOL SupportsInterface(OBJECTREF oref, MethodTable* pIntfTable); + + //-------------------------------------------------------------------- + // SupportsInterface + static void ThrowInvalidCastException(OBJECTREF *pObj, MethodTable* pCastToMT); + + //----------------------------------------------------------------- + // GetComIPFromRCW + static IUnknown* GetComIPFromRCW(OBJECTREF *pObj, MethodTable* pIntfTable); + + //----------------------------------------------------------------- + // GetComIPFromRCWThrowing + static IUnknown* GetComIPFromRCWThrowing(OBJECTREF *pObj, MethodTable* pIntfTable); + + //----------------------------------------------------------- + // create an empty ComObjectRef + static OBJECTREF CreateComObjectRef(MethodTable* pMT); + + //----------------------------------------------------------- + // Release all the data associated with the __ComObject. + static void ReleaseAllData(OBJECTREF oref); + + //----------------------------------------------------------- + // Redirection for ToString + static FCDECL1(MethodDesc *, GetRedirectedToStringMD, Object *pThisUNSAFE); + static FCDECL2(StringObject *, RedirectToString, Object *pThisUNSAFE, MethodDesc *pToStringMD); + + //----------------------------------------------------------- + // Redirection for GetHashCode + static FCDECL1(MethodDesc *, GetRedirectedGetHashCodeMD, Object *pThisUNSAFE); + static FCDECL2(int, RedirectGetHashCode, Object *pThisUNSAFE, MethodDesc *pGetHashCodeMD); + + //----------------------------------------------------------- + // Redirection for Equals + static FCDECL1(MethodDesc *, GetRedirectedEqualsMD, Object *pThisUNSAFE); + static FCDECL3(FC_BOOL_RET, RedirectEquals, Object *pThisUNSAFE, Object *pOtherUNSAFE, MethodDesc *pEqualsMD); +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<ComObject> COMOBJECTREF; +#else +typedef ComObject* COMOBJECTREF; +#endif + + +//------------------------------------------------------------- +// class UnknownWrapper, Exposed class UnknownWrapper +// +// +//------------------------------------------------------------- +class UnknownWrapper : public Object +{ +protected: + + UnknownWrapper(UnknownWrapper &wrap) {LIMITED_METHOD_CONTRACT}; // dissalow copy construction. + UnknownWrapper() {LIMITED_METHOD_CONTRACT;}; // don't instantiate this class directly + ~UnknownWrapper() {LIMITED_METHOD_CONTRACT;}; + + OBJECTREF m_WrappedObject; + +public: + OBJECTREF GetWrappedObject() + { + LIMITED_METHOD_CONTRACT; + return m_WrappedObject; + } + + void SetWrappedObject(OBJECTREF pWrappedObject) + { + LIMITED_METHOD_CONTRACT; + m_WrappedObject = pWrappedObject; + } +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<UnknownWrapper> UNKNOWNWRAPPEROBJECTREF; +#else +typedef UnknownWrapper* UNKNOWNWRAPPEROBJECTREF; +#endif + + +//------------------------------------------------------------- +// class DispatchWrapper, Exposed class DispatchWrapper +// +// +//------------------------------------------------------------- +class DispatchWrapper : public Object +{ +protected: + + DispatchWrapper(DispatchWrapper &wrap) {LIMITED_METHOD_CONTRACT}; // dissalow copy construction. + DispatchWrapper() {LIMITED_METHOD_CONTRACT;}; // don't instantiate this class directly + ~DispatchWrapper() {LIMITED_METHOD_CONTRACT;}; + + OBJECTREF m_WrappedObject; + +public: + OBJECTREF GetWrappedObject() + { + LIMITED_METHOD_CONTRACT; + return m_WrappedObject; + } + + void SetWrappedObject(OBJECTREF pWrappedObject) + { + LIMITED_METHOD_CONTRACT; + m_WrappedObject = pWrappedObject; + } +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<DispatchWrapper> DISPATCHWRAPPEROBJECTREF; +#else +typedef DispatchWrapper* DISPATCHWRAPPEROBJECTREF; +#endif + + +//------------------------------------------------------------- +// class VariantWrapper, Exposed class VARIANTWRAPPEROBJECTREF +// +// +//------------------------------------------------------------- +class VariantWrapper : public Object +{ +protected: + + VariantWrapper(VariantWrapper &wrap) {LIMITED_METHOD_CONTRACT}; // dissalow copy construction. + VariantWrapper() {LIMITED_METHOD_CONTRACT}; // don't instantiate this class directly + ~VariantWrapper() {LIMITED_METHOD_CONTRACT}; + + OBJECTREF m_WrappedObject; + +public: + OBJECTREF GetWrappedObject() + { + LIMITED_METHOD_CONTRACT; + return m_WrappedObject; + } + + void SetWrappedObject(OBJECTREF pWrappedObject) + { + LIMITED_METHOD_CONTRACT; + m_WrappedObject = pWrappedObject; + } +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<VariantWrapper> VARIANTWRAPPEROBJECTREF; +#else +typedef VariantWrapper* VARIANTWRAPPEROBJECTREF; +#endif + + +//------------------------------------------------------------- +// class ErrorWrapper, Exposed class ErrorWrapper +// +// +//------------------------------------------------------------- +class ErrorWrapper : public Object +{ +protected: + + ErrorWrapper(ErrorWrapper &wrap) {LIMITED_METHOD_CONTRACT}; // dissalow copy construction. + ErrorWrapper() {LIMITED_METHOD_CONTRACT;}; // don't instantiate this class directly + ~ErrorWrapper() {LIMITED_METHOD_CONTRACT;}; + + INT32 m_ErrorCode; + +public: + INT32 GetErrorCode() + { + LIMITED_METHOD_CONTRACT; + return m_ErrorCode; + } + + void SetErrorCode(int ErrorCode) + { + LIMITED_METHOD_CONTRACT; + m_ErrorCode = ErrorCode; + } +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<ErrorWrapper> ERRORWRAPPEROBJECTREF; +#else +typedef ErrorWrapper* ERRORWRAPPEROBJECTREF; +#endif + + +//------------------------------------------------------------- +// class CurrencyWrapper, Exposed class CurrencyWrapper +// +// +//------------------------------------------------------------- + +// Keep this in sync with code:MethodTableBuilder.CheckForSystemTypes where +// alignment requirement of the managed System.Decimal structure is computed. +#if !defined(ALIGN_ACCESS) && !defined(FEATURE_64BIT_ALIGNMENT) +#include <pshpack4.h> +#endif // !ALIGN_ACCESS && !FEATURE_64BIT_ALIGNMENT + +class CurrencyWrapper : public Object +{ +protected: + + CurrencyWrapper(CurrencyWrapper &wrap) {LIMITED_METHOD_CONTRACT}; // dissalow copy construction. + CurrencyWrapper() {LIMITED_METHOD_CONTRACT;}; // don't instantiate this class directly + ~CurrencyWrapper() {LIMITED_METHOD_CONTRACT;}; + + DECIMAL m_WrappedObject; + +public: + DECIMAL GetWrappedObject() + { + LIMITED_METHOD_CONTRACT; + return m_WrappedObject; + } + + void SetWrappedObject(DECIMAL WrappedObj) + { + LIMITED_METHOD_CONTRACT; + m_WrappedObject = WrappedObj; + } +}; + +#if !defined(ALIGN_ACCESS) && !defined(FEATURE_64BIT_ALIGNMENT) +#include <poppack.h> +#endif // !ALIGN_ACCESS && !FEATURE_64BIT_ALIGNMENT + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<CurrencyWrapper> CURRENCYWRAPPEROBJECTREF; +#else +typedef CurrencyWrapper* CURRENCYWRAPPEROBJECTREF; +#endif + +//------------------------------------------------------------- +// class BStrWrapper, Exposed class BSTRWRAPPEROBJECTREF +// +// +//------------------------------------------------------------- +class BStrWrapper : public Object +{ +protected: + + BStrWrapper(BStrWrapper &wrap) {LIMITED_METHOD_CONTRACT}; // dissalow copy construction. + BStrWrapper() {LIMITED_METHOD_CONTRACT}; // don't instantiate this class directly + ~BStrWrapper() {LIMITED_METHOD_CONTRACT}; + + STRINGREF m_WrappedObject; + +public: + STRINGREF GetWrappedObject() + { + LIMITED_METHOD_CONTRACT; + return m_WrappedObject; + } + + void SetWrappedObject(STRINGREF pWrappedObject) + { + LIMITED_METHOD_CONTRACT; + m_WrappedObject = pWrappedObject; + } +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<BStrWrapper> BSTRWRAPPEROBJECTREF; +#else +typedef BStrWrapper* BSTRWRAPPEROBJECTREF; +#endif + +#endif // FEATURE_COMINTEROP + +class StringBufferObject; +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<StringBufferObject> STRINGBUFFERREF; +#else // USE_CHECKED_OBJECTREFS +typedef StringBufferObject * STRINGBUFFERREF; +#endif // USE_CHECKED_OBJECTREFS + +// +// StringBufferObject +// +// Note that the "copy on write" bit is buried within the implementation +// of the object in order to make the implementation smaller. +// + + +class StringBufferObject : public Object +{ + friend class MscorlibBinder; + + private: + CHARARRAYREF m_ChunkChars; + StringBufferObject *m_ChunkPrevious; + UINT32 m_ChunkLength; + UINT32 m_ChunkOffset; + INT32 m_MaxCapacity; + + WCHAR* GetBuffer() + { + LIMITED_METHOD_CONTRACT; + return (WCHAR *)m_ChunkChars->GetDirectPointerToNonObjectElements(); + } + + // This function assumes that requiredLength will be less + // than the max capacity of the StringBufferObject + DWORD GetAllocationLength(DWORD dwRequiredLength) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE((INT32)dwRequiredLength <= m_MaxCapacity); + DWORD dwCurrentLength = GetArrayLength(); + + // round the current length to the nearest multiple of 2 + // that is >= the required length + if(dwCurrentLength < dwRequiredLength) + { + dwCurrentLength = (dwRequiredLength + 1) & ~1; + } + return dwCurrentLength; + } + + protected: + StringBufferObject() { LIMITED_METHOD_CONTRACT; }; + ~StringBufferObject() { LIMITED_METHOD_CONTRACT; }; + + public: + INT32 GetMaxCapacity() + { + return m_MaxCapacity; + } + + DWORD GetArrayLength() + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(m_ChunkChars); + return m_ChunkOffset + m_ChunkChars->GetNumComponents(); + } + + // Given an ANSI string, use it to replace the StringBufferObject's internal buffer + VOID ReplaceBufferWithAnsi(CHARARRAYREF *newArrayRef, __in CHAR *newChars, DWORD dwNewCapacity) + { +#ifndef DACCESS_COMPILE + SetObjectReference((OBJECTREF *)&m_ChunkChars, (OBJECTREF)(*newArrayRef), GetAppDomain()); +#endif //!DACCESS_COMPILE + WCHAR *thisChars = GetBuffer(); + // NOTE: This call to MultiByte also writes out the null terminator + // which is currently part of the String representation. + INT32 ncWritten = MultiByteToWideChar(CP_ACP, + MB_PRECOMPOSED, + newChars, + -1, + (LPWSTR)thisChars, + dwNewCapacity+1); + + if (ncWritten == 0) + { + // Normally, we'd throw an exception if the string couldn't be converted. + // In this particular case, we paper over it instead. The reason is + // that most likely reason a P/Invoke-called api returned a + // poison string is that the api failed for some reason, and hence + // exercised its right to leave the buffer in a poison state. + // Because P/Invoke cannot discover if an api failed, it cannot + // know to ignore the buffer on the out marshaling path. + // Because normal P/Invoke procedure is for the caller to check error + // codes manually, we don't want to throw an exception on him. + // We certainly don't want to randomly throw or not throw based on the + // nondeterministic contents of a buffer passed to a failing api. + *thisChars = W('\0'); + ncWritten++; + } + + m_ChunkOffset = 0; + m_ChunkLength = ncWritten-1; + m_ChunkPrevious = NULL; + } + + // Given a Unicode string, use it to replace the StringBufferObject's internal buffer + VOID ReplaceBuffer(CHARARRAYREF *newArrayRef, __in_ecount(dwNewCapacity) WCHAR *newChars, DWORD dwNewCapacity) + { + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + SO_TOLERANT; + MODE_COOPERATIVE; + } + CONTRACTL_END; +#ifndef DACCESS_COMPILE + SetObjectReference((OBJECTREF *)&m_ChunkChars, (OBJECTREF)(*newArrayRef), GetAppDomain()); +#endif //!DACCESS_COMPILE + WCHAR *thisChars = GetBuffer(); + memcpyNoGCRefs(thisChars, newChars, sizeof(WCHAR)*dwNewCapacity); + thisChars[dwNewCapacity] = W('\0'); + m_ChunkLength = dwNewCapacity; + m_ChunkPrevious = NULL; + m_ChunkOffset = 0; + } + + static void ReplaceBuffer(STRINGBUFFERREF *thisRef, __in_ecount(newLength) WCHAR *newBuffer, INT32 newLength); + static void ReplaceBufferAnsi(STRINGBUFFERREF *thisRef, __in_ecount(newCapacity) CHAR *newBuffer, INT32 newCapacity); + static INT32 LocalIndexOfString(__in_ecount(strLength) WCHAR *base, __in_ecount(patternLength) WCHAR *search, int strLength, int patternLength, int startPos); +}; + +class SafeHandle : public Object +{ + friend class MscorlibBinder; + + private: + // READ ME: + // Modifying the order or fields of this object may require + // other changes to the classlib class definition of this + // object or special handling when loading this system class. +#ifdef _DEBUG + STRINGREF m_debugStackTrace; // Where we allocated this SafeHandle +#endif + Volatile<LPVOID> m_handle; + Volatile<INT32> m_state; // Combined ref count and closed/disposed state (for atomicity) + Volatile<CLR_BOOL> m_ownsHandle; + Volatile<CLR_BOOL> m_fullyInitialized; // Did constructor finish? + + // Describe the bits in the m_state field above. + enum StateBits + { + SH_State_Closed = 0x00000001, + SH_State_Disposed = 0x00000002, + SH_State_RefCount = 0xfffffffc, + SH_RefCountOne = 4, // Amount to increment state field to yield a ref count increment of 1 + }; + + static WORD s_IsInvalidHandleMethodSlot; + static WORD s_ReleaseHandleMethodSlot; + + static void RunReleaseMethod(SafeHandle* psh); + BOOL IsFullyInitialized() const { LIMITED_METHOD_CONTRACT; return m_fullyInitialized; } + + public: + static void Init(); + + // To use the SafeHandle from native, look at the SafeHandleHolder, which + // will do the AddRef & Release for you. + LPVOID GetHandle() const { + LIMITED_METHOD_CONTRACT; + _ASSERTE(((unsigned int) m_state) >= SH_RefCountOne); + return m_handle; + } + + BOOL OwnsHandle() const + { + LIMITED_METHOD_CONTRACT; + return m_ownsHandle; + } + + static size_t GetHandleOffset() { LIMITED_METHOD_CONTRACT; return offsetof(SafeHandle, m_handle); } + + void AddRef(); + void Release(bool fDispose = false); + void Dispose(); + void SetHandle(LPVOID handle); + + static FCDECL1(void, DisposeNative, SafeHandle* refThisUNSAFE); + static FCDECL1(void, Finalize, SafeHandle* refThisUNSAFE); + static FCDECL1(void, SetHandleAsInvalid, SafeHandle* refThisUNSAFE); + static FCDECL2(void, DangerousAddRef, SafeHandle* refThisUNSAFE, CLR_BOOL *pfSuccess); + static FCDECL1(void, DangerousRelease, SafeHandle* refThisUNSAFE); +}; + +// SAFEHANDLEREF defined above because CompressedStackObject needs it + +void AcquireSafeHandle(SAFEHANDLEREF* s); +void ReleaseSafeHandle(SAFEHANDLEREF* s); + +typedef Holder<SAFEHANDLEREF*, AcquireSafeHandle, ReleaseSafeHandle> SafeHandleHolder; + +class CriticalHandle : public Object +{ + friend class MscorlibBinder; + + private: + // READ ME: + // Modifying the order or fields of this object may require + // other changes to the classlib class definition of this + // object or special handling when loading this system class. +#ifdef _DEBUG + STRINGREF m_debugStackTrace; // Where we allocated this CriticalHandle +#endif + Volatile<LPVOID> m_handle; + Volatile<CLR_BOOL> m_isClosed; + + public: + LPVOID GetHandle() const { LIMITED_METHOD_CONTRACT; return m_handle; } + static size_t GetHandleOffset() { LIMITED_METHOD_CONTRACT; return offsetof(CriticalHandle, m_handle); } + + void SetHandle(LPVOID handle) { LIMITED_METHOD_CONTRACT; m_handle = handle; } + + static FCDECL1(void, FireCustomerDebugProbe, CriticalHandle* refThisUNSAFE); +}; + + +class ReflectClassBaseObject; + +class SafeBuffer : SafeHandle +{ + private: + size_t m_numBytes; + + public: + static FCDECL1(UINT, SizeOfType, ReflectClassBaseObject* typeUNSAFE); + static FCDECL1(UINT, AlignedSizeOfType, ReflectClassBaseObject* typeUNSAFE); + static FCDECL3(void, PtrToStructure, BYTE* ptr, FC_TypedByRef structure, UINT32 sizeofT); + static FCDECL3(void, StructureToPtr, FC_TypedByRef structure, BYTE* ptr, UINT32 sizeofT); +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<CriticalHandle> CRITICALHANDLE; +typedef REF<CriticalHandle> CRITICALHANDLEREF; +#else // USE_CHECKED_OBJECTREFS +typedef CriticalHandle * CRITICALHANDLE; +typedef CriticalHandle * CRITICALHANDLEREF; +#endif // USE_CHECKED_OBJECTREFS + +// WaitHandleBase +// Base class for WaitHandle +class WaitHandleBase :public MarshalByRefObjectBaseObject +{ + friend class WaitHandleNative; + friend class MscorlibBinder; + +public: + __inline LPVOID GetWaitHandle() {LIMITED_METHOD_CONTRACT; return m_handle;} + __inline SAFEHANDLEREF GetSafeHandle() {LIMITED_METHOD_CONTRACT; return m_safeHandle;} + +private: + SAFEHANDLEREF m_safeHandle; + LPVOID m_handle; + CLR_BOOL m_hasThreadAffinity; +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<WaitHandleBase> WAITHANDLEREF; +#else // USE_CHECKED_OBJECTREFS +typedef WaitHandleBase* WAITHANDLEREF; +#endif // USE_CHECKED_OBJECTREFS + +// This class corresponds to FileStreamAsyncResult on the managed side. +class AsyncResultBase :public Object +{ + friend class MscorlibBinder; + +public: + WAITHANDLEREF GetWaitHandle() { LIMITED_METHOD_CONTRACT; return _waitHandle;} + void SetErrorCode(int errcode) { LIMITED_METHOD_CONTRACT; _errorCode = errcode;} + void SetNumBytes(int numBytes) { LIMITED_METHOD_CONTRACT; _numBytes = numBytes;} + void SetIsComplete() { LIMITED_METHOD_CONTRACT; _isComplete = TRUE; } + void SetCompletedAsynchronously() { LIMITED_METHOD_CONTRACT; _completedSynchronously = FALSE; } + + // README: + // If you modify the order of these fields, make sure to update the definition in + // BCL for this object. +private: + OBJECTREF _userCallback; + OBJECTREF _userStateObject; + + WAITHANDLEREF _waitHandle; + SAFEHANDLEREF _fileHandle; // For cancellation. + LPOVERLAPPED _overlapped; + int _EndXxxCalled; // Whether we've called EndXxx already. + int _numBytes; // number of bytes read OR written + int _errorCode; + int _numBufferedBytes; + + CLR_BOOL _isWrite; // Whether this is a read or a write + CLR_BOOL _isComplete; + CLR_BOOL _completedSynchronously; // Which thread called callback +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<AsyncResultBase> ASYNCRESULTREF; +#else // USE_CHECKED_OBJECTREFS +typedef AsyncResultBase* ASYNCRESULTREF; +#endif // USE_CHECKED_OBJECTREFS + +// This class corresponds to System.MulticastDelegate on the managed side. +class DelegateObject : public Object +{ + friend class CheckAsmOffsets; + friend class MscorlibBinder; + +public: + BOOL IsWrapperDelegate() { LIMITED_METHOD_CONTRACT; return _methodPtrAux == NULL; } + + OBJECTREF GetTarget() { LIMITED_METHOD_CONTRACT; return _target; } + void SetTarget(OBJECTREF target) { WRAPPER_NO_CONTRACT; SetObjectReference(&_target, target, GetAppDomain()); } + static int GetOffsetOfTarget() { LIMITED_METHOD_CONTRACT; return offsetof(DelegateObject, _target); } + + PCODE GetMethodPtr() { LIMITED_METHOD_CONTRACT; return _methodPtr; } + void SetMethodPtr(PCODE methodPtr) { LIMITED_METHOD_CONTRACT; _methodPtr = methodPtr; } + static int GetOffsetOfMethodPtr() { LIMITED_METHOD_CONTRACT; return offsetof(DelegateObject, _methodPtr); } + + PCODE GetMethodPtrAux() { LIMITED_METHOD_CONTRACT; return _methodPtrAux; } + void SetMethodPtrAux(PCODE methodPtrAux) { LIMITED_METHOD_CONTRACT; _methodPtrAux = methodPtrAux; } + static int GetOffsetOfMethodPtrAux() { LIMITED_METHOD_CONTRACT; return offsetof(DelegateObject, _methodPtrAux); } + + OBJECTREF GetInvocationList() { LIMITED_METHOD_CONTRACT; return _invocationList; } + void SetInvocationList(OBJECTREF invocationList) { WRAPPER_NO_CONTRACT; SetObjectReference(&_invocationList, invocationList, GetAppDomain()); } + static int GetOffsetOfInvocationList() { LIMITED_METHOD_CONTRACT; return offsetof(DelegateObject, _invocationList); } + + INT_PTR GetInvocationCount() { LIMITED_METHOD_CONTRACT; return _invocationCount; } + void SetInvocationCount(INT_PTR invocationCount) { LIMITED_METHOD_CONTRACT; _invocationCount = invocationCount; } + static int GetOffsetOfInvocationCount() { LIMITED_METHOD_CONTRACT; return offsetof(DelegateObject, _invocationCount); } + + void SetMethodBase(OBJECTREF newMethodBase) { LIMITED_METHOD_CONTRACT; SetObjectReference((OBJECTREF*)&_methodBase, newMethodBase, GetAppDomain()); } + + // README: + // If you modify the order of these fields, make sure to update the definition in + // BCL for this object. +private: + // System.Delegate + OBJECTREF _target; + OBJECTREF _methodBase; + PCODE _methodPtr; + PCODE _methodPtrAux; + // System.MulticastDelegate + OBJECTREF _invocationList; + INT_PTR _invocationCount; +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<DelegateObject> DELEGATEREF; +#else // USE_CHECKED_OBJECTREFS +typedef DelegateObject* DELEGATEREF; +#endif // USE_CHECKED_OBJECTREFS + +// This class corresponds to PermissionSet on the managed side. +class PermissionSetObject : public Object +{ + friend class MscorlibBinder; + +public: + BOOL AllPermissionsDecoded() + { + LIMITED_METHOD_CONTRACT; + return _allPermissionsDecoded == TRUE; + } + + BOOL ContainsCas() + { + LIMITED_METHOD_CONTRACT; + return _ContainsCas == TRUE; + } + + BOOL ContainsNonCas() + { + LIMITED_METHOD_CONTRACT; + return _ContainsNonCas == TRUE; + } + + BOOL CheckedForNonCas() + { + LIMITED_METHOD_CONTRACT; + return _CheckedForNonCas == TRUE; + } + + BOOL IsUnrestricted() + { + LIMITED_METHOD_CONTRACT; + return _Unrestricted == TRUE; + } + + OBJECTREF GetTokenBasedSet() + { + LIMITED_METHOD_CONTRACT; + return _permSet; + } + + + // README: + // If you modify the order of these fields, make sure to update the definition in + // BCL for this object. +private: + // Order of the fields is important as it mirrors the layout of PermissionSet + // to access the fields directly from unmanaged code given an OBJECTREF. + // Please keep them in sync when you make changes to the fields. + OBJECTREF _permSet; + STRINGREF _serializedPermissionSet; + OBJECTREF _permSetSaved; + OBJECTREF _unrestrictedPermSet; + OBJECTREF _normalPermSet; + CLR_BOOL _Unrestricted; + CLR_BOOL _allPermissionsDecoded; + CLR_BOOL _ignoreTypeLoadFailures; + CLR_BOOL _CheckedForNonCas; + CLR_BOOL _ContainsCas; + CLR_BOOL _ContainsNonCas; + CLR_BOOL _Readable; +#ifdef FEATURE_CAS_POLICY + CLR_BOOL _canUnrestrictedOverride; +#endif // FEATURE_CAS_POLICY +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<PermissionSetObject> PERMISSIONSETREF; +#else // USE_CHECKED_OBJECTREFS +typedef PermissionSetObject* PERMISSIONSETREF; +#endif // USE_CHECKED_OBJECTREFS + +// This class corresponds to TokenBasedSet on the managed side. +class TokenBasedSetObject : public Object +{ +public: + INT32 GetNumElements () { + LIMITED_METHOD_CONTRACT; + return _cElt; + } + + OBJECTREF GetPermSet () { + LIMITED_METHOD_CONTRACT; + return _Obj; + } + +private: + // If you modify the order of these fields, make sure + // to update the definition in BCL for this object. + OBJECTREF _objSet; + OBJECTREF _Obj; + OBJECTREF _Set; + INT32 _initSize; + INT32 _increment; + INT32 _cElt; + INT32 _maxIndex; +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<TokenBasedSetObject> TOKENBASEDSETREF; +#else // USE_CHECKED_OBJECTREFS +typedef TokenBasedSetObject* TOKENBASEDSETREF; +#endif // USE_CHECKED_OBJECTREFS + +// This class corresponds to PolicyStatement on the managed side. +class PolicyStatementObject : public Object +{ + friend class MscorlibBinder; +private: + PERMISSIONSETREF _permSet; +#ifdef FEATURE_CAS_POLICY + OBJECTREF _dependentEvidence; +#endif // FEATURE_CAS_POLICY + INT32 _attributes; + +public: + PERMISSIONSETREF GetPermissionSet() + { + LIMITED_METHOD_CONTRACT; + return _permSet; + } +}; +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<PolicyStatementObject> POLICYSTATEMENTREF; +#else // USE_CHECKED_OBJECTREFS +typedef PolicyStatementObject* POLICYSTATEMENTREF; +#endif // USE_CHECKED_OBJECTREFS + +// This class corresponds to ApplicationTrust on the managed side. +class ApplicationTrustObject : public Object +{ + friend class MscorlibBinder; +private: +#ifdef FEATURE_CLICKONCE + OBJECTREF _appId; + OBJECTREF _extraInfo; + OBJECTREF _elExtraInfo; +#endif // FEATURE_CLICKONCE + POLICYSTATEMENTREF _psDefaultGrant; + OBJECTREF _fullTrustAssemblies; + DWORD _grantSetSpecialFlags; +#ifdef FEATURE_CLICKONCE + CLR_BOOL _appTrustedToRun; + CLR_BOOL _persist; +#endif // FEATURE_CLICKONCE + +public: + POLICYSTATEMENTREF GetPolicyStatement() + { + LIMITED_METHOD_CONTRACT; + return _psDefaultGrant; + } + + // The grant set special flags are mapped in the BCL for the DefaultGrantSet of the ApplicationTrust. + // Since ApplicationTrust provides a reference to its DefaultGrantSet rather than a copy, the flags may + // not be in sync if user code can ever get a hold of the ApplicationTrust object. Therefore, these + // flags should only be used in code paths where we are sure that only trusted code can ever get a + // reference to the ApplicationTrust (such as the ApplicationTrust created when setting up a homogenous + // AppDomain). + DWORD GetGrantSetSpecialFlags() + { + LIMITED_METHOD_CONTRACT; + return _grantSetSpecialFlags; + } +}; +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<ApplicationTrustObject> APPLICATIONTRUSTREF; +#else // USE_CHECKED_OBJECTREFS +typedef ApplicationTrustObject* APPLICATIONTRUSTREF; +#endif // USE_CHECKED_OBJECTREFS + +// This class corresponds to SecurityPermission on the managed side. +class SecurityPermissionObject : public Object +{ +public: + DWORD GetFlags () { + LIMITED_METHOD_CONTRACT; + return _flags; + } + +private: + // If you modify the order of these fields, make sure + // to update the definition in BCL for this object. + DWORD _flags; +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<SecurityPermissionObject> SECURITYPERMISSIONREF; +#else // USE_CHECKED_OBJECTREFS +typedef SecurityPermissionObject* SECURITYPERMISSIONREF; +#endif // USE_CHECKED_OBJECTREFS + +// This class corresponds to ReflectionPermission on the managed side. +class ReflectionPermissionObject : public Object +{ +public: + DWORD GetFlags () { + LIMITED_METHOD_CONTRACT; + return _flags; + } + +private: + DWORD _flags; +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<ReflectionPermissionObject> REFLECTIONPERMISSIONREF; +#else // USE_CHECKED_OBJECTREFS +typedef ReflectionPermissionObject* REFLECTIONPERMISSIONREF; +#endif // USE_CHECKED_OBJECTREFS + +struct StackTraceElement; +class ClrDataAccess; + + +typedef DPTR(StackTraceElement) PTR_StackTraceElement; + +class StackTraceArray +{ + struct ArrayHeader + { + size_t m_size; + Thread * m_thread; + }; + + typedef DPTR(ArrayHeader) PTR_ArrayHeader; + +public: + StackTraceArray() + : m_array(static_cast<I1Array *>(NULL)) + { + WRAPPER_NO_CONTRACT; + } + + StackTraceArray(I1ARRAYREF array) + : m_array(array) + { + LIMITED_METHOD_CONTRACT; + } + + void Swap(StackTraceArray & rhs) + { + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + SO_TOLERANT; + MODE_COOPERATIVE; + } + CONTRACTL_END; + SUPPORTS_DAC; + I1ARRAYREF t = m_array; + m_array = rhs.m_array; + rhs.m_array = t; + } + + size_t Size() const + { + WRAPPER_NO_CONTRACT; + if (!m_array) + return 0; + else + return GetSize(); + } + + StackTraceElement const & operator[](size_t index) const; + StackTraceElement & operator[](size_t index); + + void Append(StackTraceElement const * begin, StackTraceElement const * end); + void AppendSkipLast(StackTraceElement const * begin, StackTraceElement const * end); + + I1ARRAYREF Get() const + { + LIMITED_METHOD_DAC_CONTRACT; + return m_array; + } + + // Deep copies the array + void CopyFrom(StackTraceArray const & src); + +private: + StackTraceArray(StackTraceArray const & rhs); + + StackTraceArray & operator=(StackTraceArray const & rhs) + { + WRAPPER_NO_CONTRACT; + StackTraceArray copy(rhs); + this->Swap(copy); + return *this; + } + + void Grow(size_t size); + void EnsureThreadAffinity(); + void CheckState() const; + + size_t Capacity() const + { + WRAPPER_NO_CONTRACT; + assert(!!m_array); + + return m_array->GetNumComponents(); + } + + size_t GetSize() const + { + WRAPPER_NO_CONTRACT; + return GetHeader()->m_size; + } + + void SetSize(size_t size) + { + WRAPPER_NO_CONTRACT; + GetHeader()->m_size = size; + } + + Thread * GetObjectThread() const + { + WRAPPER_NO_CONTRACT; + return GetHeader()->m_thread; + } + + void SetObjectThread() + { + WRAPPER_NO_CONTRACT; + GetHeader()->m_thread = GetThread(); + } + + StackTraceElement const * GetData() const + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + return dac_cast<PTR_StackTraceElement>(GetRaw() + sizeof(ArrayHeader)); + } + + PTR_StackTraceElement GetData() + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + return dac_cast<PTR_StackTraceElement>(GetRaw() + sizeof(ArrayHeader)); + } + + I1 const * GetRaw() const + { + WRAPPER_NO_CONTRACT; + assert(!!m_array); + + return const_cast<I1ARRAYREF &>(m_array)->GetDirectPointerToNonObjectElements(); + } + + PTR_I1 GetRaw() + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + assert(!!m_array); + + return dac_cast<PTR_I1>(m_array->GetDirectPointerToNonObjectElements()); + } + + ArrayHeader const * GetHeader() const + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + return dac_cast<PTR_ArrayHeader>(GetRaw()); + } + + PTR_ArrayHeader GetHeader() + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + return dac_cast<PTR_ArrayHeader>(GetRaw()); + } + + void SetArray(I1ARRAYREF const & arr) + { + LIMITED_METHOD_CONTRACT; + m_array = arr; + } + +private: + // put only things here that can be protected with GCPROTECT + I1ARRAYREF m_array; +}; + +#ifdef FEATURE_COLLECTIBLE_TYPES + +class LoaderAllocatorScoutObject : public Object +{ + friend class MscorlibBinder; + friend class LoaderAllocatorObject; + +protected: + LoaderAllocator * m_nativeLoaderAllocator; +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<LoaderAllocatorScoutObject> LOADERALLOCATORSCOUTREF; +#else // USE_CHECKED_OBJECTREFS +typedef LoaderAllocatorScoutObject* LOADERALLOCATORSCOUTREF; +#endif // USE_CHECKED_OBJECTREFS + +class LoaderAllocatorObject : public Object +{ + friend class MscorlibBinder; + +public: + PTRARRAYREF GetHandleTable() + { + LIMITED_METHOD_DAC_CONTRACT; + return (PTRARRAYREF)m_pSlots; + } + + void SetHandleTable(PTRARRAYREF handleTable) + { + LIMITED_METHOD_CONTRACT; + SetObjectReferenceUnchecked(&m_pSlots, (OBJECTREF)handleTable); + } + + INT32 GetSlotsUsed() + { + LIMITED_METHOD_CONTRACT; + return m_slotsUsed; + } + + void SetSlotsUsed(INT32 newSlotsUsed) + { + LIMITED_METHOD_CONTRACT; + m_slotsUsed = newSlotsUsed; + } + + void SetNativeLoaderAllocator(LoaderAllocator * pLoaderAllocator) + { + LIMITED_METHOD_CONTRACT; + m_pLoaderAllocatorScout->m_nativeLoaderAllocator = pLoaderAllocator; + } + + // README: + // If you modify the order of these fields, make sure to update the definition in + // BCL for this object. +protected: + LOADERALLOCATORSCOUTREF m_pLoaderAllocatorScout; + OBJECTREF m_pSlots; + INT32 m_slotsUsed; + OBJECTREF m_methodInstantiationsTable; +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<LoaderAllocatorObject> LOADERALLOCATORREF; +#else // USE_CHECKED_OBJECTREFS +typedef DPTR(LoaderAllocatorObject) PTR_LoaderAllocatorObject; +typedef PTR_LoaderAllocatorObject LOADERALLOCATORREF; +#endif // USE_CHECKED_OBJECTREFS + +#endif // FEATURE_COLLECTIBLE_TYPES + +#if !defined(DACCESS_COMPILE) +// Define the lock used to access stacktrace from an exception object +EXTERN_C SpinLock g_StackTraceArrayLock; +#endif // !defined(DACCESS_COMPILE) + +// This class corresponds to Exception on the managed side. +typedef DPTR(class ExceptionObject) PTR_ExceptionObject; +#include "pshpack4.h" +class ExceptionObject : public Object +{ + friend class MscorlibBinder; + +public: + void SetHResult(HRESULT hr) + { + LIMITED_METHOD_CONTRACT; + _HResult = hr; + } + + HRESULT GetHResult() + { + LIMITED_METHOD_CONTRACT; + return _HResult; + } + + void SetXCode(DWORD code) + { + LIMITED_METHOD_CONTRACT; + _xcode = code; + } + + DWORD GetXCode() + { + LIMITED_METHOD_CONTRACT; + return _xcode; + } + + void SetXPtrs(void* xptrs) + { + LIMITED_METHOD_CONTRACT; + _xptrs = xptrs; + } + + void* GetXPtrs() + { + LIMITED_METHOD_CONTRACT; + return _xptrs; + } + + void SetStackTrace(StackTraceArray const & stackTrace, PTRARRAYREF dynamicMethodArray); + void SetNullStackTrace(); + + void GetStackTrace(StackTraceArray & stackTrace, PTRARRAYREF * outDynamicMethodArray = NULL) const; + +#ifdef DACCESS_COMPILE + I1ARRAYREF GetStackTraceArrayObject() const + { + LIMITED_METHOD_DAC_CONTRACT; + return _stackTrace; + } +#endif // DACCESS_COMPILE + + void SetInnerException(OBJECTREF innerException) + { + WRAPPER_NO_CONTRACT; + SetObjectReference((OBJECTREF*)&_innerException, (OBJECTREF)innerException, GetAppDomain()); + } + + OBJECTREF GetInnerException() + { + LIMITED_METHOD_DAC_CONTRACT; + return _innerException; + } + + // Returns the innermost exception object - equivalent of the + // managed System.Exception.GetBaseException method. + OBJECTREF GetBaseException() + { + LIMITED_METHOD_CONTRACT; + + // Loop and get the innermost exception object + OBJECTREF oInnerMostException = NULL; + OBJECTREF oCurrent = NULL; + + oCurrent = _innerException; + while(oCurrent != NULL) + { + oInnerMostException = oCurrent; + oCurrent = ((ExceptionObject*)(Object *)OBJECTREFToObject(oCurrent))->GetInnerException(); + } + + // return the innermost exception + return oInnerMostException; + } + + void SetMessage(STRINGREF message) + { + WRAPPER_NO_CONTRACT; + SetObjectReference((OBJECTREF*)&_message, (OBJECTREF)message, GetAppDomain()); + } + + STRINGREF GetMessage() + { + LIMITED_METHOD_DAC_CONTRACT; + return _message; + } + + void SetStackTraceString(STRINGREF stackTraceString) + { + WRAPPER_NO_CONTRACT; + SetObjectReference((OBJECTREF*)&_stackTraceString, (OBJECTREF)stackTraceString, GetAppDomain()); + } + + STRINGREF GetStackTraceString() + { + LIMITED_METHOD_DAC_CONTRACT; + return _stackTraceString; + } + + STRINGREF GetRemoteStackTraceString() + { + LIMITED_METHOD_DAC_CONTRACT; + return _remoteStackTraceString; + } + + void SetHelpURL(STRINGREF helpURL) + { + WRAPPER_NO_CONTRACT; + SetObjectReference((OBJECTREF*)&_helpURL, (OBJECTREF)helpURL, GetAppDomain()); + } + + void SetSource(STRINGREF source) + { + WRAPPER_NO_CONTRACT; + SetObjectReference((OBJECTREF*)&_source, (OBJECTREF)source, GetAppDomain()); + } + + void ClearStackTraceForThrow() + { + WRAPPER_NO_CONTRACT; + SetObjectReferenceUnchecked((OBJECTREF*)&_remoteStackTraceString, NULL); + SetObjectReferenceUnchecked((OBJECTREF*)&_stackTrace, NULL); + SetObjectReferenceUnchecked((OBJECTREF*)&_stackTraceString, NULL); + } + + void ClearStackTracePreservingRemoteStackTrace() + { + WRAPPER_NO_CONTRACT; + SetObjectReferenceUnchecked((OBJECTREF*)&_stackTrace, NULL); + SetObjectReferenceUnchecked((OBJECTREF*)&_stackTraceString, NULL); + } + + // This method will set the reference to the array + // containing the watson bucket information (in byte[] form). + void SetWatsonBucketReference(OBJECTREF oWatsonBucketArray) + { + WRAPPER_NO_CONTRACT; + SetObjectReference((OBJECTREF*)&_watsonBuckets, (OBJECTREF)oWatsonBucketArray, GetAppDomain()); + } + + // This method will return the reference to the array + // containing the watson buckets + U1ARRAYREF GetWatsonBucketReference() + { + LIMITED_METHOD_CONTRACT; + return _watsonBuckets; + } + + // This method will return a BOOL to indicate if the + // watson buckets are present or not. + BOOL AreWatsonBucketsPresent() + { + LIMITED_METHOD_CONTRACT; + return (_watsonBuckets != NULL)?TRUE:FALSE; + } + + // This method will save the IP to be used for watson bucketing. + void SetIPForWatsonBuckets(UINT_PTR ip) + { + LIMITED_METHOD_CONTRACT; + + _ipForWatsonBuckets = ip; + } + + // This method will return a BOOL to indicate if Watson bucketing IP + // is present (or not). + BOOL IsIPForWatsonBucketsPresent() + { + LIMITED_METHOD_CONTRACT; + + return (_ipForWatsonBuckets != NULL); + } + + // This method returns the IP for Watson Buckets. + UINT_PTR GetIPForWatsonBuckets() + { + LIMITED_METHOD_CONTRACT; + + return _ipForWatsonBuckets; + } + + // README: + // If you modify the order of these fields, make sure to update the definition in + // BCL for this object. +private: + STRINGREF _className; //Needed for serialization. + OBJECTREF _exceptionMethod; //Needed for serialization. + STRINGREF _exceptionMethodString; //Needed for serialization. + STRINGREF _message; + OBJECTREF _data; + OBJECTREF _innerException; + STRINGREF _helpURL; + I1ARRAYREF _stackTrace; + U1ARRAYREF _watsonBuckets; + STRINGREF _stackTraceString; //Needed for serialization. + STRINGREF _remoteStackTraceString; + PTRARRAYREF _dynamicMethods; + STRINGREF _source; // Mainly used by VB. +#ifdef FEATURE_SERIALIZATION + OBJECTREF _safeSerializationManager; +#endif // FEATURE_SERIALIZATION + IN_WIN64(void* _xptrs;) + IN_WIN64(UINT_PTR _ipForWatsonBuckets;) // Contains the IP of exception for watson bucketing + INT32 _remoteStackIndex; + INT32 _HResult; + IN_WIN32(void* _xptrs;) + INT32 _xcode; + IN_WIN32(UINT_PTR _ipForWatsonBuckets;) // Contains the IP of exception for watson bucketing +}; + +// Defined in Contracts.cs +enum ContractFailureKind +{ + CONTRACT_FAILURE_PRECONDITION = 0, + CONTRACT_FAILURE_POSTCONDITION, + CONTRACT_FAILURE_POSTCONDITION_ON_EXCEPTION, + CONTRACT_FAILURE_INVARIANT, + CONTRACT_FAILURE_ASSERT, + CONTRACT_FAILURE_ASSUME, +}; + +typedef DPTR(class ContractExceptionObject) PTR_ContractExceptionObject; +class ContractExceptionObject : public ExceptionObject +{ + friend class MscorlibBinder; + +public: + ContractFailureKind GetContractFailureKind() + { + LIMITED_METHOD_CONTRACT; + + return static_cast<ContractFailureKind>(_Kind); + } + +private: + // keep these in sync with ndp/clr/src/bcl/system/diagnostics/contracts/contractsbcl.cs + IN_WIN64(INT32 _Kind;) + STRINGREF _UserMessage; + STRINGREF _Condition; + IN_WIN32(INT32 _Kind;) +}; +#include "poppack.h" + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<ContractExceptionObject> CONTRACTEXCEPTIONREF; +#else // USE_CHECKED_OBJECTREFS +typedef PTR_ContractExceptionObject CONTRACTEXCEPTIONREF; +#endif // USE_CHECKED_OBJECTREFS + +class NumberFormatInfo: public Object +{ +public: + // C++ data members // Corresponding data member in NumberFormatInfo.cs + // Also update mscorlib.h when you add/remove fields + + I4ARRAYREF cNumberGroup; // numberGroupSize + I4ARRAYREF cCurrencyGroup; // currencyGroupSize + I4ARRAYREF cPercentGroup; // percentGroupSize + + STRINGREF sPositive; // positiveSign + STRINGREF sNegative; // negativeSign + STRINGREF sNumberDecimal; // numberDecimalSeparator + STRINGREF sNumberGroup; // numberGroupSeparator + STRINGREF sCurrencyGroup; // currencyDecimalSeparator + STRINGREF sCurrencyDecimal; // currencyGroupSeparator + STRINGREF sCurrency; // currencySymbol +#ifndef FEATURE_COREFX_GLOBALIZATION + STRINGREF sAnsiCurrency; // ansiCurrencySymbol +#endif + STRINGREF sNaN; // nanSymbol + STRINGREF sPositiveInfinity; // positiveInfinitySymbol + STRINGREF sNegativeInfinity; // negativeInfinitySymbol + STRINGREF sPercentDecimal; // percentDecimalSeparator + STRINGREF sPercentGroup; // percentGroupSeparator + STRINGREF sPercent; // percentSymbol + STRINGREF sPerMille; // perMilleSymbol + + PTRARRAYREF sNativeDigits; // nativeDigits (a string array) + +#ifndef FEATURE_COREFX_GLOBALIZATION + INT32 iDataItem; // Index into the CultureInfo Table. Only used from managed code. +#endif + INT32 cNumberDecimals; // numberDecimalDigits + INT32 cCurrencyDecimals; // currencyDecimalDigits + INT32 cPosCurrencyFormat; // positiveCurrencyFormat + INT32 cNegCurrencyFormat; // negativeCurrencyFormat + INT32 cNegativeNumberFormat; // negativeNumberFormat + INT32 cPositivePercentFormat; // positivePercentFormat + INT32 cNegativePercentFormat; // negativePercentFormat + INT32 cPercentDecimals; // percentDecimalDigits +#ifndef FEATURE_COREFX_GLOBALIZATION + INT32 iDigitSubstitution; // digitSubstitution +#endif + + CLR_BOOL bIsReadOnly; // Is this NumberFormatInfo ReadOnly? +#ifndef FEATURE_COREFX_GLOBALIZATION + CLR_BOOL bUseUserOverride; // Flag to use user override. Only used from managed code. +#endif + CLR_BOOL bIsInvariant; // Is this the NumberFormatInfo for the Invariant Culture? +#ifndef FEATURE_COREFX_GLOBALIZATION + CLR_BOOL bvalidForParseAsNumber; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett) + CLR_BOOL bvalidForParseAsCurrency; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett) +#endif +}; + +typedef NumberFormatInfo * NUMFMTREF; + +//=============================================================================== +// #NullableFeature +// #NullableArchitecture +// +// In a nutshell it is counterintuitive to have a boxed Nullable<T>, since a boxed +// object already has a representation for null (the null pointer), and having +// multiple representations for the 'not present' value just causes grief. Thus the +// feature is build make Nullable<T> box to a boxed<T> (not boxed<Nullable<T>). +// +// We want to do this in a way that does not impact the perf of the runtime in the +// non-nullable case. +// +// To do this we need to +// * Modify the boxing helper code:JIT_Box (we don't need a special one because +// the JIT inlines the common case, so this only gets call in uncommon cases) +// * Make a new helper for the Unbox case (see code:JIT_Unbox_Nullable) +// * Plumb the JIT to ask for what kind of Boxing helper is needed +// (see code:CEEInfo.getBoxHelper, code:CEEInfo.getUnBoxHelper +// * change all the places in the CLR where we box or unbox by hand, and force +// them to use code:MethodTable.Box, and code:MethodTable.Unbox which in +// turn call code:Nullable.Box and code:Nullable.UnBox, most of these +// are in reflection, and remoting (passing and returning value types). +// +// #NullableVerification +// +// Sadly, the IL Verifier also needs to know about this change. Basically the 'box' +// instruction returns a boxed(T) (not a boxed(Nullable<T>)) for the purposes of +// verfication. The JIT finds out what box returns by calling back to the EE with +// the code:CEEInfo.getTypeForBox API. +// +// #NullableDebugging +// +// Sadly, because the debugger also does its own boxing 'by hand' for expression +// evaluation inside visual studio, it measn that debuggers also need to be aware +// of the fact that Nullable<T> boxes to a boxed<T>. It is the responcibility of +// debuggers to follow this convention (which is why this is sad). +// + +//=============================================================================== +// Nullable represents the managed generic value type Nullable<T> +// +// The runtime has special logic for this value class. When it is boxed +// it becomes either null or a boxed T. Similarly a boxed T can be unboxed +// either as a T (as normal), or as a Nullable<T> +// +// See code:Nullable#NullableArchitecture for more. +// +class Nullable { + Nullable(); // This is purposefully undefined. Do not make instances + // of this class. +public: + static void CheckFieldOffsets(TypeHandle nullableType); + static BOOL IsNullableType(TypeHandle nullableType); + static BOOL IsNullableForType(TypeHandle nullableType, MethodTable* paramMT); + static BOOL IsNullableForTypeNoGC(TypeHandle nullableType, MethodTable* paramMT); + + static OBJECTREF Box(void* src, MethodTable* nullable); + static BOOL UnBox(void* dest, OBJECTREF boxedVal, MethodTable* destMT); + static BOOL UnBoxNoGC(void* dest, OBJECTREF boxedVal, MethodTable* destMT); + static BOOL UnBoxIntoArgNoGC(ArgDestination *argDest, OBJECTREF boxedVal, MethodTable* destMT); + static void UnBoxNoCheck(void* dest, OBJECTREF boxedVal, MethodTable* destMT); + static OBJECTREF BoxedNullableNull(TypeHandle nullableType) { return 0; } + + // if 'Obj' is a true boxed nullable, return the form we want (either null or a boxed T) + static OBJECTREF NormalizeBox(OBJECTREF obj); + + static inline CLR_BOOL HasValue(void *src, MethodTable *nullableMT) + { + Nullable *nullable = (Nullable *)src; + return *(nullable->HasValueAddr(nullableMT)); + } + + static inline void *Value(void *src, MethodTable *nullableMT) + { + Nullable *nullable = (Nullable *)src; + return nullable->ValueAddr(nullableMT); + } + +private: + static BOOL IsNullableForTypeHelper(MethodTable* nullableMT, MethodTable* paramMT); + static BOOL IsNullableForTypeHelperNoGC(MethodTable* nullableMT, MethodTable* paramMT); + + CLR_BOOL* HasValueAddr(MethodTable* nullableMT); + void* ValueAddr(MethodTable* nullableMT); +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF<ExceptionObject> EXCEPTIONREF; +#else // USE_CHECKED_OBJECTREFS +typedef PTR_ExceptionObject EXCEPTIONREF; +#endif // USE_CHECKED_OBJECTREFS + +#endif // _OBJECT_H_ |