summaryrefslogtreecommitdiff
path: root/src/vm/custommarshalerinfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/custommarshalerinfo.cpp')
-rw-r--r--src/vm/custommarshalerinfo.cpp641
1 files changed, 641 insertions, 0 deletions
diff --git a/src/vm/custommarshalerinfo.cpp b/src/vm/custommarshalerinfo.cpp
new file mode 100644
index 0000000000..f9cb61296d
--- /dev/null
+++ b/src/vm/custommarshalerinfo.cpp
@@ -0,0 +1,641 @@
+// 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.
+//
+// File: CustomMarshalerInfo.cpp
+//
+
+//
+// Custom marshaler information used when marshaling
+// a parameter with a custom marshaler.
+//
+
+
+#include "common.h"
+
+
+#include "custommarshalerinfo.h"
+#include "mlinfo.h"
+#include "mdaassistants.h"
+#include "sigbuilder.h"
+
+//==========================================================================
+// Implementation of the custom marshaler info class.
+//==========================================================================
+
+CustomMarshalerInfo::CustomMarshalerInfo(BaseDomain *pDomain, TypeHandle hndCustomMarshalerType, TypeHandle hndManagedType, LPCUTF8 strCookie, DWORD cCookieStrBytes)
+: m_NativeSize(0)
+, m_hndManagedType(hndManagedType)
+, m_hndCustomMarshaler(NULL)
+, m_pMarshalNativeToManagedMD(NULL)
+, m_pMarshalManagedToNativeMD(NULL)
+, m_pCleanUpNativeDataMD(NULL)
+, m_pCleanUpManagedDataMD(NULL)
+, m_bDataIsByValue(FALSE)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pDomain));
+ }
+ CONTRACTL_END;
+
+
+ // Make sure the custom marshaller implements ICustomMarshaler.
+ if (!hndCustomMarshalerType.GetMethodTable()->CanCastToNonVariantInterface(MscorlibBinder::GetClass(CLASS__ICUSTOM_MARSHALER)))
+ {
+ DefineFullyQualifiedNameForClassW()
+ COMPlusThrow(kApplicationException,
+ IDS_EE_ICUSTOMMARSHALERNOTIMPL,
+ GetFullyQualifiedNameForClassW(hndCustomMarshalerType.GetMethodTable()));
+ }
+
+ // Determine if this type is a value class.
+ m_bDataIsByValue = m_hndManagedType.GetMethodTable()->IsValueType();
+
+ // Custom marshalling of value classes is not currently supported.
+ if (m_bDataIsByValue)
+ COMPlusThrow(kNotSupportedException, W("NotSupported_ValueClassCM"));
+
+#ifndef CROSSGEN_COMPILE
+ // Run the <clinit> on the marshaler since it might not have run yet.
+ hndCustomMarshalerType.GetMethodTable()->EnsureInstanceActive();
+ hndCustomMarshalerType.GetMethodTable()->CheckRunClassInitThrowing();
+
+ // Create a COM+ string that will contain the string cookie.
+ STRINGREF CookieStringObj = StringObject::NewString(strCookie, cCookieStrBytes);
+ GCPROTECT_BEGIN(CookieStringObj);
+#endif
+
+ // Load the method desc's for all the methods in the ICustomMarshaler interface.
+ m_pMarshalNativeToManagedMD = GetCustomMarshalerMD(CustomMarshalerMethods_MarshalNativeToManaged, hndCustomMarshalerType);
+ m_pMarshalManagedToNativeMD = GetCustomMarshalerMD(CustomMarshalerMethods_MarshalManagedToNative, hndCustomMarshalerType);
+ m_pCleanUpNativeDataMD = GetCustomMarshalerMD(CustomMarshalerMethods_CleanUpNativeData, hndCustomMarshalerType);
+ m_pCleanUpManagedDataMD = GetCustomMarshalerMD(CustomMarshalerMethods_CleanUpManagedData, hndCustomMarshalerType);
+
+ // Load the method desc for the static method to retrieve the instance.
+ MethodDesc *pGetCustomMarshalerMD = GetCustomMarshalerMD(CustomMarshalerMethods_GetInstance, hndCustomMarshalerType);
+
+ // If the GetInstance method is generic, get an instantiating stub for it -
+ // the CallDescr infrastructure doesn't know how to pass secret generic arguments.
+ if (pGetCustomMarshalerMD->RequiresInstMethodTableArg())
+ {
+ pGetCustomMarshalerMD = MethodDesc::FindOrCreateAssociatedMethodDesc(
+ pGetCustomMarshalerMD,
+ hndCustomMarshalerType.GetMethodTable(),
+ FALSE, // forceBoxedEntryPoint
+ Instantiation(), // methodInst
+ FALSE, // allowInstParam
+ FALSE); // forceRemotableMethod
+
+ _ASSERTE(!pGetCustomMarshalerMD->RequiresInstMethodTableArg());
+ }
+
+#ifndef CROSSGEN_COMPILE
+ MethodDescCallSite getCustomMarshaler(pGetCustomMarshalerMD, (OBJECTREF*)&CookieStringObj);
+
+ pGetCustomMarshalerMD->EnsureActive();
+
+ // Prepare the arguments that will be passed to GetCustomMarshaler.
+ ARG_SLOT GetCustomMarshalerArgs[] = {
+ ObjToArgSlot(CookieStringObj)
+ };
+
+ // Call the GetCustomMarshaler method to retrieve the custom marshaler to use.
+ OBJECTREF CustomMarshalerObj = getCustomMarshaler.Call_RetOBJECTREF(GetCustomMarshalerArgs);
+ if (!CustomMarshalerObj)
+ {
+ DefineFullyQualifiedNameForClassW()
+ COMPlusThrow(kApplicationException,
+ IDS_EE_NOCUSTOMMARSHALER,
+ GetFullyQualifiedNameForClassW(hndCustomMarshalerType.GetMethodTable()));
+ }
+ m_hndCustomMarshaler = pDomain->CreateHandle(CustomMarshalerObj);
+
+ // Retrieve the size of the native data.
+ if (m_bDataIsByValue)
+ {
+ // <TODO>@TODO(DM): Call GetNativeDataSize() to retrieve the size of the native data.</TODO>
+ _ASSERTE(!"Value classes are not yet supported by the custom marshaler!");
+ }
+ else
+ {
+ m_NativeSize = sizeof(void *);
+ }
+
+ GCPROTECT_END();
+#endif
+}
+
+
+CustomMarshalerInfo::~CustomMarshalerInfo()
+{
+ WRAPPER_NO_CONTRACT;
+#ifndef CROSSGEN_COMPILE
+ if (m_hndCustomMarshaler)
+ {
+ DestroyHandle(m_hndCustomMarshaler);
+ m_hndCustomMarshaler = NULL;
+ }
+#endif
+}
+
+
+void *CustomMarshalerInfo::operator new(size_t size, LoaderHeap *pHeap)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ INJECT_FAULT(COMPlusThrowOM());
+ PRECONDITION(CheckPointer(pHeap));
+ }
+ CONTRACTL_END;
+
+ return pHeap->AllocMem(S_SIZE_T(sizeof(CustomMarshalerInfo)));
+}
+
+
+void CustomMarshalerInfo::operator delete(void *pMem)
+{
+ // Instances of this class are always allocated on the loader heap so
+ // the delete operator has nothing to do.
+ LIMITED_METHOD_CONTRACT;
+}
+
+#ifndef CROSSGEN_COMPILE
+OBJECTREF CustomMarshalerInfo::InvokeMarshalNativeToManagedMeth(void *pNative)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pNative, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ if (!pNative)
+ return NULL;
+
+ MethodDescCallSite marshalNativeToManaged(m_pMarshalNativeToManagedMD, m_hndCustomMarshaler);
+
+ ARG_SLOT Args[] = {
+ ObjToArgSlot(ObjectFromHandle(m_hndCustomMarshaler)),
+ PtrToArgSlot(pNative)
+ };
+
+ return marshalNativeToManaged.Call_RetOBJECTREF(Args);
+}
+
+
+void *CustomMarshalerInfo::InvokeMarshalManagedToNativeMeth(OBJECTREF MngObj)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ }
+ CONTRACTL_END;
+
+ void *RetVal = NULL;
+
+ if (!MngObj)
+ return NULL;
+
+ GCPROTECT_BEGIN (MngObj);
+ MethodDescCallSite marshalManagedToNative(m_pMarshalManagedToNativeMD, m_hndCustomMarshaler);
+
+ ARG_SLOT Args[] = {
+ ObjToArgSlot(ObjectFromHandle(m_hndCustomMarshaler)),
+ ObjToArgSlot(MngObj)
+ };
+
+ RetVal = marshalManagedToNative.Call_RetLPVOID(Args);
+ GCPROTECT_END ();
+
+ return RetVal;
+}
+
+
+void CustomMarshalerInfo::InvokeCleanUpNativeMeth(void *pNative)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pNative, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ if (!pNative)
+ return;
+
+ MethodDescCallSite cleanUpNativeData(m_pCleanUpNativeDataMD, m_hndCustomMarshaler);
+
+ ARG_SLOT Args[] = {
+ ObjToArgSlot(ObjectFromHandle(m_hndCustomMarshaler)),
+ PtrToArgSlot(pNative)
+ };
+
+ cleanUpNativeData.Call(Args);
+}
+
+
+void CustomMarshalerInfo::InvokeCleanUpManagedMeth(OBJECTREF MngObj)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ }
+ CONTRACTL_END;
+
+ if (!MngObj)
+ return;
+
+ GCPROTECT_BEGIN (MngObj);
+ MethodDescCallSite cleanUpManagedData(m_pCleanUpManagedDataMD, m_hndCustomMarshaler);
+
+ ARG_SLOT Args[] = {
+ ObjToArgSlot(ObjectFromHandle(m_hndCustomMarshaler)),
+ ObjToArgSlot(MngObj)
+ };
+
+ cleanUpManagedData.Call(Args);
+ GCPROTECT_END ();
+}
+
+#endif // CROSSGEN_COMPILE
+MethodDesc *CustomMarshalerInfo::GetCustomMarshalerMD(EnumCustomMarshalerMethods Method, TypeHandle hndCustomMarshalertype)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ }
+ CONTRACTL_END;
+
+
+ MethodTable *pMT = hndCustomMarshalertype.AsMethodTable();
+
+ _ASSERTE(pMT->CanCastToNonVariantInterface(MscorlibBinder::GetClass(CLASS__ICUSTOM_MARSHALER)));
+
+ MethodDesc *pMD = NULL;
+
+ switch (Method)
+ {
+ case CustomMarshalerMethods_MarshalNativeToManaged:
+ pMD = pMT->GetMethodDescForInterfaceMethod(
+ MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__MARSHAL_NATIVE_TO_MANAGED));
+ break;
+ case CustomMarshalerMethods_MarshalManagedToNative:
+ pMD = pMT->GetMethodDescForInterfaceMethod(
+ MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__MARSHAL_MANAGED_TO_NATIVE));
+ break;
+ case CustomMarshalerMethods_CleanUpNativeData:
+ pMD = pMT->GetMethodDescForInterfaceMethod(
+ MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__CLEANUP_NATIVE_DATA));
+ break;
+
+ case CustomMarshalerMethods_CleanUpManagedData:
+ pMD = pMT->GetMethodDescForInterfaceMethod(
+ MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__CLEANUP_MANAGED_DATA));
+ break;
+ case CustomMarshalerMethods_GetNativeDataSize:
+ pMD = pMT->GetMethodDescForInterfaceMethod(
+ MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__GET_NATIVE_DATA_SIZE));
+ break;
+ case CustomMarshalerMethods_GetInstance:
+ // Must look this up by name since it's static
+ pMD = MemberLoader::FindMethod(pMT, "GetInstance", &gsig_SM_Str_RetICustomMarshaler);
+ if (!pMD)
+ {
+ DefineFullyQualifiedNameForClassW()
+ COMPlusThrow(kApplicationException,
+ IDS_EE_GETINSTANCENOTIMPL,
+ GetFullyQualifiedNameForClassW(pMT));
+ }
+ break;
+ default:
+ _ASSERTE(!"Unknown custom marshaler method");
+ }
+
+ _ASSERTE(pMD && "Unable to find specified CustomMarshaler method");
+
+ // Ensure that the value types in the signature are loaded.
+ MetaSig::EnsureSigValueTypesLoaded(pMD);
+
+ // Return the specified method desc.
+ return pMD;
+}
+
+#ifndef CROSSGEN_COMPILE
+
+//==========================================================================
+// Implementation of the custom marshaler hashtable helper.
+//==========================================================================
+
+EEHashEntry_t * EECMHelperHashtableHelper::AllocateEntry(EECMHelperHashtableKey *pKey, BOOL bDeepCopy, void* pHeap)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ INJECT_FAULT(return NULL;);
+ }
+ CONTRACTL_END;
+
+ EEHashEntry_t *pEntry;
+
+ if (bDeepCopy)
+ {
+ S_SIZE_T cbEntry = S_SIZE_T(sizeof(EEHashEntry) - 1 + sizeof(EECMHelperHashtableKey));
+ cbEntry += S_SIZE_T(pKey->GetMarshalerTypeNameByteCount());
+ cbEntry += S_SIZE_T(pKey->GetCookieStringByteCount());
+ cbEntry += S_SIZE_T(pKey->GetMarshalerInstantiation().GetNumArgs()) * S_SIZE_T(sizeof(LPVOID));
+
+ if (cbEntry.IsOverflow())
+ return NULL;
+
+ pEntry = (EEHashEntry_t *) new (nothrow) BYTE[cbEntry.Value()];
+ if (!pEntry)
+ return NULL;
+
+ EECMHelperHashtableKey *pEntryKey = (EECMHelperHashtableKey *) pEntry->Key;
+ pEntryKey->m_cMarshalerTypeNameBytes = pKey->GetMarshalerTypeNameByteCount();
+ pEntryKey->m_strMarshalerTypeName = (LPSTR) pEntry->Key + sizeof(EECMHelperHashtableKey);
+ pEntryKey->m_cCookieStrBytes = pKey->GetCookieStringByteCount();
+ pEntryKey->m_strCookie = (LPSTR) pEntry->Key + sizeof(EECMHelperHashtableKey) + pEntryKey->m_cMarshalerTypeNameBytes;
+ pEntryKey->m_Instantiation = Instantiation(
+ (TypeHandle *) (pEntryKey->m_strCookie + pEntryKey->m_cCookieStrBytes),
+ pKey->GetMarshalerInstantiation().GetNumArgs());
+ pEntryKey->m_bSharedHelper = pKey->IsSharedHelper();
+ memcpy((void*)pEntryKey->m_strMarshalerTypeName, pKey->GetMarshalerTypeName(), pKey->GetMarshalerTypeNameByteCount());
+ memcpy((void*)pEntryKey->m_strCookie, pKey->GetCookieString(), pKey->GetCookieStringByteCount());
+ memcpy((void*)pEntryKey->m_Instantiation.GetRawArgs(), pKey->GetMarshalerInstantiation().GetRawArgs(),
+ pEntryKey->m_Instantiation.GetNumArgs() * sizeof(LPVOID));
+ }
+ else
+ {
+ pEntry = (EEHashEntry_t *)
+ new (nothrow) BYTE[sizeof(EEHashEntry) - 1 + sizeof(EECMHelperHashtableKey)];
+ if (!pEntry)
+ return NULL;
+
+ EECMHelperHashtableKey *pEntryKey = (EECMHelperHashtableKey *) pEntry->Key;
+ pEntryKey->m_cMarshalerTypeNameBytes = pKey->GetMarshalerTypeNameByteCount();
+ pEntryKey->m_strMarshalerTypeName = pKey->GetMarshalerTypeName();
+ pEntryKey->m_cCookieStrBytes = pKey->GetCookieStringByteCount();
+ pEntryKey->m_strCookie = pKey->GetCookieString();
+ pEntryKey->m_Instantiation = Instantiation(pKey->GetMarshalerInstantiation());
+ pEntryKey->m_bSharedHelper = pKey->IsSharedHelper();
+ }
+
+ return pEntry;
+}
+
+
+void EECMHelperHashtableHelper::DeleteEntry(EEHashEntry_t *pEntry, void* pHeap)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ PRECONDITION(CheckPointer(pEntry));
+ }
+ CONTRACTL_END;
+
+ delete[] (BYTE*)pEntry;
+}
+
+
+BOOL EECMHelperHashtableHelper::CompareKeys(EEHashEntry_t *pEntry, EECMHelperHashtableKey *pKey)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ PRECONDITION(CheckPointer(pEntry));
+ PRECONDITION(CheckPointer(pKey));
+ }
+ CONTRACTL_END;
+
+ EECMHelperHashtableKey *pEntryKey = (EECMHelperHashtableKey *) pEntry->Key;
+
+ if (pEntryKey->IsSharedHelper() != pKey->IsSharedHelper())
+ return FALSE;
+
+ if (pEntryKey->GetMarshalerTypeNameByteCount() != pKey->GetMarshalerTypeNameByteCount())
+ return FALSE;
+
+ if (memcmp(pEntryKey->GetMarshalerTypeName(), pKey->GetMarshalerTypeName(), pEntryKey->GetMarshalerTypeNameByteCount()) != 0)
+ return FALSE;
+
+ if (pEntryKey->GetCookieStringByteCount() != pKey->GetCookieStringByteCount())
+ return FALSE;
+
+ if (memcmp(pEntryKey->GetCookieString(), pKey->GetCookieString(), pEntryKey->GetCookieStringByteCount()) != 0)
+ return FALSE;
+
+ DWORD dwNumTypeArgs = pEntryKey->GetMarshalerInstantiation().GetNumArgs();
+ if (dwNumTypeArgs != pKey->GetMarshalerInstantiation().GetNumArgs())
+ return FALSE;
+
+ for (DWORD i = 0; i < dwNumTypeArgs; i++)
+ {
+ if (pEntryKey->GetMarshalerInstantiation()[i] != pKey->GetMarshalerInstantiation()[i])
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+DWORD EECMHelperHashtableHelper::Hash(EECMHelperHashtableKey *pKey)
+{
+ WRAPPER_NO_CONTRACT;
+
+ return (DWORD)
+ (HashBytes((const BYTE *) pKey->GetMarshalerTypeName(), pKey->GetMarshalerTypeNameByteCount()) +
+ HashBytes((const BYTE *) pKey->GetCookieString(), pKey->GetCookieStringByteCount()) +
+ HashBytes((const BYTE *) pKey->GetMarshalerInstantiation().GetRawArgs(), pKey->GetMarshalerInstantiation().GetNumArgs() * sizeof(LPVOID)) +
+ (pKey->IsSharedHelper() ? 1 : 0));
+}
+
+
+OBJECTREF CustomMarshalerHelper::InvokeMarshalNativeToManagedMeth(void *pNative)
+{
+ WRAPPER_NO_CONTRACT;
+ return GetCustomMarshalerInfo()->InvokeMarshalNativeToManagedMeth(pNative);
+}
+
+
+void *CustomMarshalerHelper::InvokeMarshalManagedToNativeMeth(OBJECTREF MngObj)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ }
+ CONTRACTL_END;
+
+ void *RetVal = NULL;
+
+ GCPROTECT_BEGIN(MngObj)
+ {
+ CustomMarshalerInfo *pCMInfo = GetCustomMarshalerInfo();
+ RetVal = pCMInfo->InvokeMarshalManagedToNativeMeth(MngObj);
+ }
+ GCPROTECT_END();
+
+ return RetVal;
+}
+
+
+void CustomMarshalerHelper::InvokeCleanUpNativeMeth(void *pNative)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ }
+ CONTRACTL_END;
+
+ OBJECTREF ExceptionObj = NULL;
+ GCPROTECT_BEGIN(ExceptionObj)
+ {
+ EX_TRY
+ {
+ GetCustomMarshalerInfo()->InvokeCleanUpNativeMeth(pNative);
+ }
+ EX_CATCH
+ {
+ ExceptionObj = GET_THROWABLE();
+ }
+ EX_END_CATCH(SwallowAllExceptions);
+
+#ifdef MDA_SUPPORTED
+ if (ExceptionObj != NULL)
+ {
+ TypeHandle typeCustomMarshaler = GetCustomMarshalerInfo()->GetCustomMarshalerType();
+ MDA_TRIGGER_ASSISTANT(MarshalCleanupError, ReportErrorCustomMarshalerCleanup(typeCustomMarshaler, &ExceptionObj));
+ }
+#endif
+ }
+ GCPROTECT_END();
+}
+
+
+void CustomMarshalerHelper::InvokeCleanUpManagedMeth(OBJECTREF MngObj)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ }
+ CONTRACTL_END;
+
+ GCPROTECT_BEGIN(MngObj)
+ {
+ CustomMarshalerInfo *pCMInfo = GetCustomMarshalerInfo();
+ pCMInfo->InvokeCleanUpManagedMeth(MngObj);
+ }
+ GCPROTECT_END();
+}
+
+
+void *NonSharedCustomMarshalerHelper::operator new(size_t size, LoaderHeap *pHeap)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ INJECT_FAULT(COMPlusThrowOM());
+ PRECONDITION(CheckPointer(pHeap));
+ }
+ CONTRACTL_END;
+
+ return pHeap->AllocMem(S_SIZE_T(sizeof(NonSharedCustomMarshalerHelper)));
+}
+
+
+void NonSharedCustomMarshalerHelper::operator delete(void *pMem)
+{
+ // Instances of this class are always allocated on the loader heap so
+ // the delete operator has nothing to do.
+ LIMITED_METHOD_CONTRACT;
+}
+
+
+SharedCustomMarshalerHelper::SharedCustomMarshalerHelper(Assembly *pAssembly, TypeHandle hndManagedType, LPCUTF8 strMarshalerTypeName, DWORD cMarshalerTypeNameBytes, LPCUTF8 strCookie, DWORD cCookieStrBytes)
+: m_pAssembly(pAssembly)
+, m_hndManagedType(hndManagedType)
+, m_cMarshalerTypeNameBytes(cMarshalerTypeNameBytes)
+, m_strMarshalerTypeName(strMarshalerTypeName)
+, m_cCookieStrBytes(cCookieStrBytes)
+, m_strCookie(strCookie)
+{
+ WRAPPER_NO_CONTRACT;
+}
+
+
+void *SharedCustomMarshalerHelper::operator new(size_t size, LoaderHeap *pHeap)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ INJECT_FAULT(COMPlusThrowOM());
+ PRECONDITION(CheckPointer(pHeap));
+ }
+ CONTRACTL_END;
+
+ return pHeap->AllocMem(S_SIZE_T(sizeof(SharedCustomMarshalerHelper)));
+}
+
+
+void SharedCustomMarshalerHelper::operator delete(void *pMem)
+{
+ // Instances of this class are always allocated on the loader heap so
+ // the delete operator has nothing to do.
+ LIMITED_METHOD_CONTRACT;
+}
+
+
+CustomMarshalerInfo *SharedCustomMarshalerHelper::GetCustomMarshalerInfo()
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ }
+ CONTRACTL_END;
+
+ // Retrieve the marshalling data for the current app domain.
+ EEMarshalingData *pMarshalingData = GetThread()->GetDomain()->GetMarshalingData();
+
+ // Retrieve the custom marshaling information for the current shared custom
+ // marshaling helper.
+ return pMarshalingData->GetCustomMarshalerInfo(this);
+}
+
+
+#endif // CROSSGEN_COMPILE
+