summaryrefslogtreecommitdiff
path: root/src/vm/dispparammarshaler.cpp
diff options
context:
space:
mode:
authordotnet-bot <dotnet-bot@microsoft.com>2015-01-30 14:14:42 -0800
committerdotnet-bot <dotnet-bot@microsoft.com>2015-01-30 14:14:42 -0800
commitef1e2ab328087c61a6878c1e84f4fc5d710aebce (patch)
treedee1bbb89e9d722e16b0d1485e3cdd1b6c8e2cfa /src/vm/dispparammarshaler.cpp
downloadcoreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.gz
coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.bz2
coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.zip
Initial commit to populate CoreCLR repo
[tfs-changeset: 1407945]
Diffstat (limited to 'src/vm/dispparammarshaler.cpp')
-rw-r--r--src/vm/dispparammarshaler.cpp646
1 files changed, 646 insertions, 0 deletions
diff --git a/src/vm/dispparammarshaler.cpp b/src/vm/dispparammarshaler.cpp
new file mode 100644
index 0000000000..77d8d8b1a0
--- /dev/null
+++ b/src/vm/dispparammarshaler.cpp
@@ -0,0 +1,646 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+//
+// File: DispParamMarshaler.cpp
+//
+
+//
+// Implementation of dispatch parameter marshalers.
+//
+
+
+#include "common.h"
+
+#include "dispparammarshaler.h"
+#include "olevariant.h"
+#include "dispatchinfo.h"
+#include "fieldmarshaler.h"
+#include "comdelegate.h"
+
+BOOL DispParamMarshaler::RequiresManagedCleanup()
+{
+ LIMITED_METHOD_CONTRACT;
+ return FALSE;
+}
+
+void DispParamMarshaler::MarshalNativeToManaged(VARIANT *pSrcVar, OBJECTREF *pDestObj)
+{
+ WRAPPER_NO_CONTRACT;
+ OleVariant::MarshalObjectForOleVariant(pSrcVar, pDestObj);
+}
+
+void DispParamMarshaler::MarshalManagedToNative(OBJECTREF *pSrcObj, VARIANT *pDestVar)
+{
+ WRAPPER_NO_CONTRACT;
+ OleVariant::MarshalOleVariantForObject(pSrcObj, pDestVar);
+}
+
+void DispParamMarshaler::MarshalManagedToNativeRef(OBJECTREF *pSrcObj, VARIANT *pRefVar)
+{
+ WRAPPER_NO_CONTRACT;
+ OleVariant::MarshalOleRefVariantForObject(pSrcObj, pRefVar);
+}
+
+void DispParamMarshaler::CleanUpManaged(OBJECTREF *pObj)
+{
+ LIMITED_METHOD_CONTRACT;
+}
+
+void DispParamCurrencyMarshaler::MarshalManagedToNative(OBJECTREF *pSrcObj, VARIANT *pDestVar)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pDestVar));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK;
+
+ // Convert the managed decimal to a VARIANT containing a decimal.
+ OleVariant::MarshalOleVariantForObject(pSrcObj, pDestVar);
+ _ASSERTE(pDestVar->vt == VT_DECIMAL);
+
+ // Coerce the decimal to a currency.
+ IfFailThrow(SafeVariantChangeType(pDestVar, pDestVar, 0, VT_CY));
+}
+
+void DispParamOleColorMarshaler::MarshalNativeToManaged(VARIANT *pSrcVar, OBJECTREF *pDestObj)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pSrcVar));
+ }
+ CONTRACTL_END;
+
+ BOOL bByref = FALSE;
+ VARTYPE vt = V_VT(pSrcVar);
+
+ // Handle byref VARIANTS
+ if (vt & VT_BYREF)
+ {
+ vt = vt & ~VT_BYREF;
+ bByref = TRUE;
+ }
+
+ // Validate the OLE variant type.
+ if (vt != VT_I4 && vt != VT_UI4)
+ COMPlusThrow(kArgumentException, IDS_EE_INVALID_OLE_VARIANT);
+
+ // Retrieve the OLECOLOR.
+ OLE_COLOR OleColor = bByref ? *V_UI4REF(pSrcVar) : V_UI4(pSrcVar);
+
+ // Convert the OLECOLOR to a System.Drawing.Color.
+ SYSTEMCOLOR MngColor;
+ ConvertOleColorToSystemColor(OleColor, &MngColor);
+
+ // Box the System.Drawing.Color value class and give back the boxed object.
+ TypeHandle hndColorType =
+ GetThread()->GetDomain()->GetMarshalingData()->GetOleColorMarshalingInfo()->GetColorType();
+
+ *pDestObj = hndColorType.GetMethodTable()->Box(&MngColor);
+}
+
+void DispParamOleColorMarshaler::MarshalManagedToNative(OBJECTREF *pSrcObj, VARIANT *pDestVar)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pDestVar));
+ }
+ CONTRACTL_END;
+
+ // Clear the destination VARIANT.
+ SafeVariantClear(pDestVar);
+
+ // Convert the System.Drawing.Color to an OLECOLOR.
+ V_VT(pDestVar) = VT_UI4;
+ V_UI4(pDestVar) = ConvertSystemColorToOleColor(pSrcObj);
+}
+
+void DispParamOleColorMarshaler::MarshalManagedToNativeRef(OBJECTREF *pSrcObj, VARIANT *pRefVar)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pRefVar));
+ }
+ CONTRACTL_END;
+
+ _ASSERTE(V_VT(pRefVar) == (VT_I4 | VT_BYREF) || V_VT(pRefVar) == (VT_UI4 | VT_BYREF));
+
+ // Convert the System.Drawing.Color to an OLECOLOR.
+ *V_UI4REF(pRefVar) = ConvertSystemColorToOleColor(pSrcObj);
+}
+
+void DispParamErrorMarshaler::MarshalManagedToNative(OBJECTREF *pSrcObj, VARIANT *pDestVar)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pDestVar));
+ }
+ CONTRACTL_END;
+
+ // Convert the managed decimal to a VARIANT containing a VT_I4 or VT_UI4.
+ OleVariant::MarshalOleVariantForObject(pSrcObj, pDestVar);
+ _ASSERTE(V_VT(pDestVar) == VT_I4 || V_VT(pDestVar) == VT_UI4);
+
+ // Since VariantChangeType refuses to coerce an I4 or an UI4 to a VT_ERROR, just
+ // wack the variant type directly.
+ V_VT(pDestVar) = VT_ERROR;
+}
+
+void DispParamInterfaceMarshaler::MarshalNativeToManaged(VARIANT *pSrcVar, OBJECTREF *pDestObj)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pSrcVar));
+ PRECONDITION(IsProtectedByGCFrame(pDestObj));
+ }
+ CONTRACTL_END;
+
+ BOOL bByref = FALSE;
+ VARTYPE vt = V_VT(pSrcVar);
+
+ // Handle byref VARIANTS
+ if (vt & VT_BYREF)
+ {
+ vt = vt & ~VT_BYREF;
+ bByref = TRUE;
+ }
+
+ // Validate the OLE variant type.
+ if (vt != VT_UNKNOWN && vt != VT_DISPATCH)
+ COMPlusThrow(kArgumentException, IDS_EE_INVALID_OLE_VARIANT);
+
+ // Retrieve the IP.
+ IUnknown *pUnk = bByref ? *V_UNKNOWNREF(pSrcVar) : V_UNKNOWN(pSrcVar);
+
+ // Convert the IP to an OBJECTREF.
+ GetObjectRefFromComIP(pDestObj, pUnk, m_pClassMT, /* pItfMT = */ NULL, m_bClassIsHint ? ObjFromComIP::CLASS_IS_HINT : ObjFromComIP::NONE);
+}
+
+void DispParamInterfaceMarshaler::MarshalManagedToNative(OBJECTREF *pSrcObj, VARIANT *pDestVar)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pDestVar));
+ }
+ CONTRACTL_END;
+
+ SafeVariantClear(pDestVar);
+ if (m_pIntfMT != NULL)
+ {
+ V_UNKNOWN(pDestVar) = GetComIPFromObjectRef(pSrcObj, m_pIntfMT);
+ }
+ else
+ {
+ V_UNKNOWN(pDestVar) = GetComIPFromObjectRef(pSrcObj, m_bDispatch ? ComIpType_Dispatch : ComIpType_Unknown, NULL);
+ }
+
+ V_VT(pDestVar) = static_cast<VARTYPE>(m_bDispatch ? VT_DISPATCH : VT_UNKNOWN);
+}
+
+#ifdef FEATURE_CLASSIC_COMINTEROP
+void DispParamArrayMarshaler::MarshalNativeToManaged(VARIANT *pSrcVar, OBJECTREF *pDestObj)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pSrcVar));
+ }
+ CONTRACTL_END;
+
+ VARTYPE vt = m_ElementVT;
+ MethodTable *pElemMT = m_pElementMT;
+
+ // Validate the OLE variant type.
+ if ((V_VT(pSrcVar) & VT_ARRAY) == 0)
+ COMPlusThrow(kArgumentException, IDS_EE_INVALID_OLE_VARIANT);
+
+ // Retrieve the SAFEARRAY pointer.
+ SAFEARRAY *pSafeArray = V_VT(pSrcVar) & VT_BYREF ? *V_ARRAYREF(pSrcVar) : V_ARRAY(pSrcVar);
+
+ if (pSafeArray)
+ {
+ // Retrieve the variant type if it is not specified for the parameter.
+ if (vt == VT_EMPTY)
+ vt = V_VT(pSrcVar) & ~VT_ARRAY | VT_BYREF;
+
+ if (!pElemMT && vt == VT_RECORD)
+ pElemMT = OleVariant::GetElementTypeForRecordSafeArray(pSafeArray).GetMethodTable();
+
+ // Create an array from the SAFEARRAY.
+ *(BASEARRAYREF*)pDestObj = OleVariant::CreateArrayRefForSafeArray(pSafeArray, vt, pElemMT);
+
+ // Convert the contents of the SAFEARRAY.
+ OleVariant::MarshalArrayRefForSafeArray(pSafeArray, (BASEARRAYREF*)pDestObj, vt, pElemMT);
+ }
+ else
+ {
+ *pDestObj = NULL;
+ }
+}
+
+void DispParamArrayMarshaler::MarshalManagedToNative(OBJECTREF *pSrcObj, VARIANT *pDestVar)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pDestVar));
+ }
+ CONTRACTL_END;
+
+ SafeArrayPtrHolder pSafeArray = NULL;
+ VARTYPE vt = m_ElementVT;
+ MethodTable *pElemMT = m_pElementMT;
+
+ // Clear the destination VARIANT.
+ SafeVariantClear(pDestVar);
+
+ if (*pSrcObj != NULL)
+ {
+ // Retrieve the VARTYPE if it is not specified for the parameter.
+ if (vt == VT_EMPTY)
+ vt = OleVariant::GetElementVarTypeForArrayRef(*((BASEARRAYREF*)pSrcObj));
+
+ // Retrieve the element method table if it is not specified for the parameter.
+ if (!pElemMT)
+ {
+ TypeHandle tempHandle = OleVariant::GetArrayElementTypeWrapperAware((BASEARRAYREF*)pSrcObj);
+ pElemMT = tempHandle.GetMethodTable();
+ }
+
+ // Allocate the safe array based on the source object and the destination VT.
+ pSafeArray = OleVariant::CreateSafeArrayForArrayRef((BASEARRAYREF*)pSrcObj, vt, pElemMT);
+ _ASSERTE(pSafeArray);
+
+ // Marshal the contents of the SAFEARRAY.
+ OleVariant::MarshalSafeArrayForArrayRef((BASEARRAYREF*)pSrcObj, pSafeArray, vt, pElemMT);
+ }
+
+ // Store the resulting SAFEARRAY in the destination VARIANT.
+ V_ARRAY(pDestVar) = pSafeArray;
+ V_VT(pDestVar) = VT_ARRAY | vt;
+
+ // Don't destroy the safearray.
+ pSafeArray.SuppressRelease();
+}
+
+void DispParamArrayMarshaler::MarshalManagedToNativeRef(OBJECTREF *pSrcObj, VARIANT *pRefVar)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pRefVar));
+ }
+ CONTRACTL_END;
+
+ VARIANT vtmp;
+ VARTYPE RefVt = V_VT(pRefVar) & ~VT_BYREF;
+
+ // Clear the contents of the original variant.
+ OleVariant::ExtractContentsFromByrefVariant(pRefVar, &vtmp);
+ SafeVariantClear(&vtmp);
+
+ // Marshal the array to a temp VARIANT.
+ memset(&vtmp, 0, sizeof(VARIANT));
+ MarshalManagedToNative(pSrcObj, &vtmp);
+
+ // Verify that the type of the temp VARIANT and the destination byref VARIANT
+ // are the same.
+ if (V_VT(&vtmp) != RefVt)
+ {
+ SafeVariantClear(&vtmp);
+ COMPlusThrow(kInvalidCastException, IDS_EE_CANNOT_COERCE_BYREF_VARIANT);
+ }
+
+ // Copy the converted variant back into the byref variant.
+ OleVariant::InsertContentsIntoByrefVariant(&vtmp, pRefVar);
+}
+#endif // FEATURE_CLASSIC_COMINTEROP
+
+void DispParamRecordMarshaler::MarshalNativeToManaged(VARIANT *pSrcVar, OBJECTREF *pDestObj)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ INJECT_FAULT(COMPlusThrowOM());
+ PRECONDITION(CheckPointer(pSrcVar));
+ }
+ CONTRACTL_END;
+
+ GUID argGuid;
+ GUID paramGuid;
+ HRESULT hr = S_OK;
+ VARTYPE vt = V_VT(pSrcVar);
+
+ // Handle byref VARIANTS
+ if (vt & VT_BYREF)
+ vt = vt & ~VT_BYREF;
+
+ // Validate the OLE variant type.
+ if (vt != VT_RECORD)
+ COMPlusThrow(kArgumentException, IDS_EE_INVALID_OLE_VARIANT);
+
+ // Make sure an IRecordInfo is specified.
+ IRecordInfo *pRecInfo = pSrcVar->pRecInfo;
+ if (!pRecInfo)
+ COMPlusThrow(kArgumentException, IDS_EE_INVALID_OLE_VARIANT);
+
+ // Make sure the GUID of the IRecordInfo matches the guid of the
+ // parameter type.
+ {
+ GCX_PREEMP();
+ IfFailThrow(pRecInfo->GetGuid(&argGuid));
+ }
+ if (argGuid != GUID_NULL)
+ {
+ m_pRecordMT->GetGuid(&paramGuid, TRUE);
+ if (paramGuid != argGuid)
+ COMPlusThrow(kArgumentException, IDS_EE_INVALID_OLE_VARIANT);
+ }
+
+ OBJECTREF BoxedValueClass = NULL;
+ GCPROTECT_BEGIN(BoxedValueClass)
+ {
+ LPVOID pvRecord = pSrcVar->pvRecord;
+ if (pvRecord)
+ {
+ // Allocate an instance of the boxed value class and copy the contents
+ // of the record into it.
+ BoxedValueClass = m_pRecordMT->Allocate();
+ FmtClassUpdateCLR(&BoxedValueClass, (BYTE*)pvRecord);
+ }
+
+ *pDestObj = BoxedValueClass;
+ }
+ GCPROTECT_END();
+}
+
+void DispParamRecordMarshaler::MarshalManagedToNative(OBJECTREF *pSrcObj, VARIANT *pDestVar)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pDestVar));
+ }
+ CONTRACTL_END;
+
+ // Clear the destination VARIANT.
+ SafeVariantClear(pDestVar);
+
+ // Convert the value class to a VT_RECORD.
+ OleVariant::ConvertValueClassToVariant(pSrcObj, pDestVar);
+
+ // Set the VT in the VARIANT.
+ V_VT(pDestVar) = VT_RECORD;
+}
+
+void DispParamDelegateMarshaler::MarshalNativeToManaged(VARIANT *pSrcVar, OBJECTREF *pDestObj)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ INJECT_FAULT(COMPlusThrowOM());
+ PRECONDITION(CheckPointer(pSrcVar));
+ }
+ CONTRACTL_END;
+
+ void *pDelegate = NULL;
+
+ switch(V_VT(pSrcVar))
+ {
+#ifdef _WIN64
+ case VT_I8:
+ pDelegate = reinterpret_cast<void*>(static_cast<INT_PTR>(V_I8(pSrcVar)));
+ break;
+
+ case VT_UI8:
+ pDelegate = reinterpret_cast<void*>(static_cast<UINT_PTR>(V_UI8(pSrcVar)));
+ break;
+#else
+ case VT_I4:
+ pDelegate = reinterpret_cast<void*>(static_cast<INT_PTR>(V_I4(pSrcVar)));
+ break;
+
+ case VT_UI4:
+ pDelegate = reinterpret_cast<void*>(static_cast<UINT_PTR>(V_UI4(pSrcVar)));
+ break;
+#endif
+ default :
+ COMPlusThrow(kArgumentException, IDS_EE_INVALID_OLE_VARIANT);
+
+ }
+
+ if (pDelegate == NULL)
+ SetObjectReference(pDestObj, NULL, GetAppDomain());
+ else
+ SetObjectReference(pDestObj, COMDelegate::ConvertToDelegate(pDelegate, m_pDelegateMT), GetAppDomain());
+}
+
+void DispParamDelegateMarshaler::MarshalManagedToNative(OBJECTREF *pSrcObj, VARIANT *pDestVar)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pDestVar));
+ }
+ CONTRACTL_END;
+
+ // Clear the destination VARIANT.
+ SafeVariantClear(pDestVar);
+
+ // Convert to VARIANT
+#ifdef _WIN64
+ V_VT(pDestVar) = VT_I8;
+#else
+ V_VT(pDestVar) = VT_I4;
+#endif
+
+ // ConvertToCallback automatically takes care of the pSrcObj == NULL case
+ void *pDelegate = (void*) COMDelegate::ConvertToCallback(*pSrcObj);
+
+#ifdef _WIN64
+ V_I8(pDestVar) = static_cast<INT64>(reinterpret_cast<INT_PTR>(pDelegate));
+#else
+ V_I4(pDestVar) = static_cast<INT32>(reinterpret_cast<INT_PTR>(pDelegate));
+#endif
+}
+
+BOOL DispParamCustomMarshaler::RequiresManagedCleanup()
+{
+ LIMITED_METHOD_CONTRACT;
+ return TRUE;
+}
+
+void DispParamCustomMarshaler::MarshalNativeToManaged(VARIANT *pSrcVar, OBJECTREF *pDestObj)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pSrcVar));
+ }
+ CONTRACTL_END;
+
+ BOOL bByref = FALSE;
+ VARTYPE vt = V_VT(pSrcVar);
+
+ // Handle byref VARIANTS
+ if (vt & VT_BYREF)
+ {
+ vt = vt & ~VT_BYREF;
+ bByref = TRUE;
+ }
+
+ // Make sure the source VARIANT is of a valid type.
+ if (vt != VT_I4 && vt != VT_UI4 && vt != VT_UNKNOWN && vt != VT_DISPATCH)
+ COMPlusThrow(kInvalidCastException, IDS_EE_INVALID_VT_FOR_CUSTOM_MARHALER);
+
+ // Retrieve the IUnknown pointer.
+ IUnknown *pUnk = bByref ? *V_UNKNOWNREF(pSrcVar) : V_UNKNOWN(pSrcVar);
+
+ // Marshal the contents of the VARIANT using the custom marshaler.
+ *pDestObj = m_pCMHelper->InvokeMarshalNativeToManagedMeth(pUnk);
+}
+
+void DispParamCustomMarshaler::MarshalManagedToNative(OBJECTREF *pSrcObj, VARIANT *pDestVar)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pDestVar));
+ }
+ CONTRACTL_END;
+
+ SafeComHolder<IUnknown> pUnk = NULL;
+ SafeComHolder<IDispatch> pDisp = NULL;
+
+ // Convert the object using the custom marshaler.
+ SafeVariantClear(pDestVar);
+
+ // Invoke the MarshalManagedToNative method.
+ pUnk = (IUnknown*)m_pCMHelper->InvokeMarshalManagedToNativeMeth(*pSrcObj);
+ if (!pUnk)
+ {
+ // Put a null IDispath pointer in the VARIANT.
+ V_VT(pDestVar) = VT_DISPATCH;
+ V_DISPATCH(pDestVar) = NULL;
+ }
+ else
+ {
+ // QI the object for IDispatch.
+ HRESULT hr = SafeQueryInterface(pUnk, IID_IDispatch, (IUnknown **)&pDisp);
+ LogInteropQI(pUnk, IID_IDispatch, hr, "DispParamCustomMarshaler::MarshalManagedToNative");
+ if (SUCCEEDED(hr))
+ {
+ // Release the IUnknown pointer since we will put the IDispatch pointer in
+ // the VARIANT.
+ ULONG cbRef = SafeRelease(pUnk);
+ pUnk.SuppressRelease();
+ LogInteropRelease(pUnk, cbRef, "Release IUnknown");
+
+ // Put the IDispatch pointer into the VARIANT.
+ V_VT(pDestVar) = VT_DISPATCH;
+ V_DISPATCH(pDestVar) = pDisp;
+ pDisp.SuppressRelease();
+ }
+ else
+ {
+ // Put the IUnknown pointer into the VARIANT.
+ V_VT(pDestVar) = VT_UNKNOWN;
+ V_UNKNOWN(pDestVar) = pUnk;
+ pUnk.SuppressRelease();
+ }
+ }
+}
+
+void DispParamCustomMarshaler::MarshalManagedToNativeRef(OBJECTREF *pSrcObj, VARIANT *pRefVar)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pRefVar));
+ }
+ CONTRACTL_END;
+
+ VARTYPE RefVt = V_VT(pRefVar) & ~VT_BYREF;
+ VARIANT vtmp;
+
+ // Clear the contents of the original variant.
+ OleVariant::ExtractContentsFromByrefVariant(pRefVar, &vtmp);
+ SafeVariantClear(&vtmp);
+
+ // Convert the object using the custom marshaler.
+ V_UNKNOWN(&vtmp) = (IUnknown*)m_pCMHelper->InvokeMarshalManagedToNativeMeth(*pSrcObj);
+ V_VT(&vtmp) = m_vt;
+
+ // Call VariantChangeType if required.
+ if (V_VT(&vtmp) != RefVt)
+ {
+ HRESULT hr = SafeVariantChangeType(&vtmp, &vtmp, 0, RefVt);
+ if (FAILED(hr))
+ {
+ SafeVariantClear(&vtmp);
+ if (hr == DISP_E_TYPEMISMATCH)
+ COMPlusThrow(kInvalidCastException, IDS_EE_CANNOT_COERCE_BYREF_VARIANT);
+ else
+ COMPlusThrowHR(hr);
+ }
+ }
+
+ // Copy the converted variant back into the byref variant.
+ OleVariant::InsertContentsIntoByrefVariant(&vtmp, pRefVar);
+}
+
+void DispParamCustomMarshaler::CleanUpManaged(OBJECTREF *pObj)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ }
+ CONTRACTL_END;
+ m_pCMHelper->InvokeCleanUpManagedMeth(*pObj);
+}