summaryrefslogtreecommitdiff
path: root/src/vm/appdomainhelper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/appdomainhelper.cpp')
-rw-r--r--src/vm/appdomainhelper.cpp546
1 files changed, 546 insertions, 0 deletions
diff --git a/src/vm/appdomainhelper.cpp b/src/vm/appdomainhelper.cpp
new file mode 100644
index 0000000000..2c0531648f
--- /dev/null
+++ b/src/vm/appdomainhelper.cpp
@@ -0,0 +1,546 @@
+// 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.
+
+
+//
+
+#include "common.h"
+
+#ifdef FEATURE_REMOTING
+
+#include "appdomainhelper.h"
+#include "appdomain.inl"
+
+void AppDomainHelper::CopyEncodingToByteArray(IN PBYTE pbData,
+ IN DWORD cbData,
+ OUT OBJECTREF* pArray)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(cbData==0 || pbData!=NULL);
+ PRECONDITION(CheckPointer(pArray));
+ }
+ CONTRACTL_END;
+ PREFIX_ASSUME(pArray != NULL);
+
+ U1ARRAYREF pObj;
+
+ if(cbData) {
+ pObj = (U1ARRAYREF)AllocatePrimitiveArray(ELEMENT_TYPE_U1,cbData);
+ memcpyNoGCRefs(pObj->m_Array, pbData, cbData);
+ *pArray = (OBJECTREF) pObj;
+ } else
+ *pArray = NULL;
+
+ VALIDATEOBJECTREF(*pArray);
+}
+
+
+void AppDomainHelper::CopyByteArrayToEncoding(IN U1ARRAYREF* pArray,
+ OUT PBYTE* ppbData,
+ OUT DWORD* pcbData)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_COOPERATIVE;
+ PRECONDITION(pArray!=NULL);
+ PRECONDITION(ppbData!=NULL);
+ PRECONDITION(pcbData!=NULL);
+ }
+ CONTRACTL_END;
+
+ VALIDATEOBJECTREF(*pArray);
+
+ if (*pArray == NULL) {
+ *ppbData = NULL;
+ *pcbData = 0;
+ return;
+ }
+
+ DWORD size = (*pArray)->GetNumComponents();
+ if(size) {
+ *ppbData = new BYTE[size];
+ *pcbData = size;
+
+ CopyMemory(*ppbData, (*pArray)->GetDirectPointerToNonObjectElements(), size);
+ }
+}
+
+
+struct MarshalObjectArgs : public CtxTransitionBaseArgs
+{
+ OBJECTREF* orObject;
+ U1ARRAYREF* porBlob;
+};
+
+void MarshalObjectADCallback(MarshalObjectArgs * args)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ }
+ CONTRACTL_END;
+ MethodDescCallSite marshalObject(METHOD__APP_DOMAIN__MARSHAL_OBJECT);
+
+ ARG_SLOT argsCall[] = {
+ ObjToArgSlot(*(args->orObject))
+ };
+
+ *(args->porBlob) = (U1ARRAYREF) marshalObject.Call_RetOBJECTREF(argsCall);
+}
+
+
+// Marshal a single object into a serialized blob.
+void AppDomainHelper::MarshalObject(ADID appDomain,
+ IN OBJECTREF *orObject, // Object must be GC protected
+ OUT U1ARRAYREF *porBlob)
+{
+
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(orObject!=NULL);
+ PRECONDITION(porBlob!=NULL);
+ PRECONDITION(IsProtectedByGCFrame(orObject));
+ }
+ CONTRACTL_END;
+
+ VALIDATEOBJECTREF(*orObject);
+
+ MarshalObjectArgs args;
+ args.orObject = orObject;
+ args.porBlob = porBlob;
+
+ MakeCallWithPossibleAppDomainTransition(appDomain, (FPAPPDOMAINCALLBACK) MarshalObjectADCallback, &args);
+
+ VALIDATEOBJECTREF(*porBlob);
+
+}
+
+void AppDomainHelper::MarshalObject(IN OBJECTREF *orObject, // Object must be GC protected
+ OUT U1ARRAYREF *porBlob)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(orObject!=NULL);
+ PRECONDITION(porBlob!=NULL);
+ PRECONDITION(IsProtectedByGCFrame(orObject));
+ }
+ CONTRACTL_END;
+
+ VALIDATEOBJECTREF(*orObject);
+
+ MethodDescCallSite marshalObject(METHOD__APP_DOMAIN__MARSHAL_OBJECT);
+
+ ARG_SLOT argsCall[] = {
+ ObjToArgSlot(*orObject)
+ };
+
+ *porBlob = (U1ARRAYREF) marshalObject.Call_RetOBJECTREF(argsCall);
+
+ VALIDATEOBJECTREF(*porBlob);
+}
+
+// Marshal a single object into a serialized blob.
+void AppDomainHelper::MarshalObject(IN AppDomain *pDomain,
+ IN OBJECTREF *orObject, // Object must be GC protected
+ OUT BYTE **ppbBlob,
+ OUT DWORD *pcbBlob)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(pDomain!=NULL);
+ PRECONDITION(orObject!=NULL);
+ PRECONDITION(ppbBlob!=NULL);
+ PRECONDITION(pcbBlob!=NULL);
+ PRECONDITION(IsProtectedByGCFrame(orObject));
+ }
+ CONTRACTL_END;
+
+ VALIDATEOBJECTREF(*orObject);
+
+ U1ARRAYREF orBlob = NULL;
+
+ GCPROTECT_BEGIN(orBlob);
+
+ MethodDescCallSite marshalObject(METHOD__APP_DOMAIN__MARSHAL_OBJECT);
+
+ ENTER_DOMAIN_PTR(pDomain,ADV_RUNNINGIN)
+ {
+ ARG_SLOT args[] =
+ {
+ ObjToArgSlot(*orObject)
+ };
+
+ orBlob = (U1ARRAYREF) marshalObject.Call_RetOBJECTREF(args);
+ }
+ END_DOMAIN_TRANSITION;
+
+ if (orBlob != NULL)
+ CopyByteArrayToEncoding(&orBlob,
+ ppbBlob,
+ pcbBlob);
+ GCPROTECT_END();
+}
+
+// Marshal two objects into serialized blobs.
+void AppDomainHelper::MarshalObjects(IN AppDomain *pDomain,
+ IN OBJECTREF *orObject1,
+ IN OBJECTREF *orObject2,
+ OUT BYTE **ppbBlob1,
+ OUT DWORD *pcbBlob1,
+ OUT BYTE **ppbBlob2,
+ OUT DWORD *pcbBlob2)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(pDomain!=NULL);
+ PRECONDITION(orObject1!=NULL);
+ PRECONDITION(ppbBlob1!=NULL);
+ PRECONDITION(pcbBlob1!=NULL);
+ PRECONDITION(orObject2!=NULL);
+ PRECONDITION(ppbBlob2!=NULL);
+ PRECONDITION(pcbBlob2!=NULL);
+ PRECONDITION(IsProtectedByGCFrame(orObject1));
+ PRECONDITION(IsProtectedByGCFrame(orObject2));
+ }
+ CONTRACTL_END;
+
+ VALIDATEOBJECTREF(*orObject1);
+ VALIDATEOBJECTREF(*orObject2);
+
+ struct _gc {
+ U1ARRAYREF orBlob1;
+ U1ARRAYREF orBlob2;
+ } gc;
+ ZeroMemory(&gc, sizeof(gc));
+
+ GCPROTECT_BEGIN(gc);
+
+ MethodDescCallSite marshalObjects(METHOD__APP_DOMAIN__MARSHAL_OBJECTS);
+
+ ENTER_DOMAIN_PTR(pDomain,ADV_RUNNINGIN)
+ {
+ ARG_SLOT args[] =
+ {
+ ObjToArgSlot(*orObject1),
+ ObjToArgSlot(*orObject2),
+ PtrToArgSlot(&gc.orBlob2),
+ };
+
+ gc.orBlob1 = (U1ARRAYREF) marshalObjects.Call_RetOBJECTREF(args);
+ }
+ END_DOMAIN_TRANSITION;
+
+ if (gc.orBlob1 != NULL)
+ {
+ CopyByteArrayToEncoding(&gc.orBlob1,
+ ppbBlob1,
+ pcbBlob1);
+ }
+
+ if (gc.orBlob2 != NULL)
+ {
+ CopyByteArrayToEncoding(&gc.orBlob2,
+ ppbBlob2,
+ pcbBlob2);
+ }
+
+ GCPROTECT_END();
+}
+
+// Unmarshal a single object from a serialized blob.
+// Callers must GC protect both porBlob and porObject.
+void AppDomainHelper::UnmarshalObject(IN AppDomain *pDomain,
+ IN U1ARRAYREF *porBlob, // Object must be GC protected
+ OUT OBJECTREF *porObject) // Object must be GC protected
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(pDomain!=NULL);
+ PRECONDITION(porBlob!=NULL);
+ PRECONDITION(porObject!=NULL);
+ PRECONDITION(IsProtectedByGCFrame(porBlob));
+ PRECONDITION(IsProtectedByGCFrame(porObject));
+ }
+ CONTRACTL_END;
+
+ VALIDATEOBJECTREF(*porBlob);
+
+ MethodDescCallSite unmarshalObject(METHOD__APP_DOMAIN__UNMARSHAL_OBJECT);
+
+ ENTER_DOMAIN_PTR(pDomain,ADV_RUNNINGIN)
+ {
+ ARG_SLOT args[] =
+ {
+ ObjToArgSlot(*porBlob)
+ };
+
+ *porObject = unmarshalObject.Call_RetOBJECTREF(args);
+ }
+ END_DOMAIN_TRANSITION;
+
+ VALIDATEOBJECTREF(*porObject);
+}
+
+// Unmarshal a single object from a serialized blob.
+void AppDomainHelper::UnmarshalObject(IN AppDomain *pDomain,
+ IN BYTE *pbBlob,
+ IN DWORD cbBlob,
+ OUT OBJECTREF *porObject)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(pDomain!=NULL);
+ PRECONDITION(porObject!=NULL);
+ PRECONDITION(IsProtectedByGCFrame(porObject));
+ }
+ CONTRACTL_END;
+
+ OBJECTREF orBlob = NULL;
+
+ MethodDescCallSite unmarshalObject(METHOD__APP_DOMAIN__UNMARSHAL_OBJECT);
+
+ ENTER_DOMAIN_PTR(pDomain,ADV_RUNNINGIN)
+ {
+ GCPROTECT_BEGIN(orBlob);
+
+ AppDomainHelper::CopyEncodingToByteArray(pbBlob,
+ cbBlob,
+ &orBlob);
+
+ ARG_SLOT args[] =
+ {
+ ObjToArgSlot(orBlob)
+ };
+
+ *porObject = unmarshalObject.Call_RetOBJECTREF(args);
+
+ GCPROTECT_END();
+ }
+ END_DOMAIN_TRANSITION;
+
+ VALIDATEOBJECTREF(*porObject);
+}
+
+// Unmarshal two objects from serialized blobs.
+void AppDomainHelper::UnmarshalObjects(IN AppDomain *pDomain,
+ IN BYTE *pbBlob1,
+ IN DWORD cbBlob1,
+ IN BYTE *pbBlob2,
+ IN DWORD cbBlob2,
+ OUT OBJECTREF *porObject1,
+ OUT OBJECTREF *porObject2)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(pDomain!=NULL);
+ PRECONDITION(porObject1!=NULL);
+ PRECONDITION(porObject2!=NULL);
+ PRECONDITION(IsProtectedByGCFrame(porObject1));
+ PRECONDITION(IsProtectedByGCFrame(porObject2));
+ }
+ CONTRACTL_END;
+
+ MethodDescCallSite unmarshalObjects(METHOD__APP_DOMAIN__UNMARSHAL_OBJECTS);
+
+ struct _gc {
+ OBJECTREF orBlob1;
+ OBJECTREF orBlob2;
+ OBJECTREF orObject2;
+ } gc;
+ ZeroMemory(&gc, sizeof(gc));
+
+ ENTER_DOMAIN_PTR(pDomain,ADV_RUNNINGIN)
+ {
+
+ GCPROTECT_BEGIN(gc);
+
+ AppDomainHelper::CopyEncodingToByteArray(pbBlob1,
+ cbBlob1,
+ &gc.orBlob1);
+
+ AppDomainHelper::CopyEncodingToByteArray(pbBlob2,
+ cbBlob2,
+ &gc.orBlob2);
+
+ ARG_SLOT args[] =
+ {
+ ObjToArgSlot(gc.orBlob1),
+ ObjToArgSlot(gc.orBlob2),
+ PtrToArgSlot(&gc.orObject2),
+ };
+
+ *porObject1 = unmarshalObjects.Call_RetOBJECTREF(args);
+ *porObject2 = gc.orObject2;
+
+ GCPROTECT_END();
+ }
+ END_DOMAIN_TRANSITION;
+
+ VALIDATEOBJECTREF(*porObject1);
+ VALIDATEOBJECTREF(*porObject2);
+}
+
+// Copy an object from the given appdomain into the current appdomain.
+OBJECTREF AppDomainHelper::CrossContextCopyFrom(IN ADID dwDomainId,
+ IN OBJECTREF *orObject) // Object must be GC protected
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(orObject!=NULL);
+ PRECONDITION(IsProtectedByGCFrame(orObject));
+ }
+ CONTRACTL_END;
+
+ struct _gc
+ {
+ U1ARRAYREF orBlob;
+ OBJECTREF pResult;
+ } gc;
+ ZeroMemory(&gc, sizeof(gc));
+
+ GCPROTECT_BEGIN(gc);
+ AppDomainHelper::MarshalObject(dwDomainId, orObject, &gc.orBlob);
+ AppDomainHelper::UnmarshalObject(GetAppDomain(), &gc.orBlob, &gc.pResult);
+ GCPROTECT_END();
+ VALIDATEOBJECTREF(gc.pResult);
+ return gc.pResult;
+}
+
+// Copy an object from the given appdomain into the current appdomain.
+OBJECTREF AppDomainHelper::CrossContextCopyTo(IN ADID dwDomainId,
+ IN OBJECTREF *orObject) // Object must be GC protected
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(orObject!=NULL);
+ PRECONDITION(IsProtectedByGCFrame(orObject));
+ }
+ CONTRACTL_END;
+
+
+ struct _gc
+ {
+ U1ARRAYREF orBlob;
+ OBJECTREF pResult;
+ } gc;
+ ZeroMemory(&gc, sizeof(gc));
+
+ GCPROTECT_BEGIN(gc);
+ AppDomainHelper::MarshalObject(orObject, &gc.orBlob);
+ ENTER_DOMAIN_ID(dwDomainId);
+ AppDomainHelper::UnmarshalObject(GetAppDomain(),&gc.orBlob, &gc.pResult);
+ END_DOMAIN_TRANSITION;
+ GCPROTECT_END();
+ VALIDATEOBJECTREF(gc.pResult);
+ return gc.pResult;
+
+}
+
+// Copy an object from the given appdomain into the current appdomain.
+OBJECTREF AppDomainHelper::CrossContextCopyFrom(IN AppDomain *pDomain,
+ IN OBJECTREF *orObject) // Object must be GC protected
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(orObject!=NULL);
+ PRECONDITION(IsProtectedByGCFrame(orObject));
+ PRECONDITION(pDomain!=NULL);
+ PRECONDITION(pDomain != GetAppDomain());
+ }
+ CONTRACTL_END;
+
+ VALIDATEOBJECTREF(*orObject);
+
+ struct _gc {
+ U1ARRAYREF orBlob;
+ OBJECTREF result;
+ } gc;
+ ZeroMemory(&gc, sizeof(gc));
+
+ GCPROTECT_BEGIN(gc);
+ ENTER_DOMAIN_PTR(pDomain, ADV_RUNNINGIN);
+ AppDomainHelper::MarshalObject(orObject, &gc.orBlob);
+ END_DOMAIN_TRANSITION;
+ AppDomainHelper::UnmarshalObject(GetAppDomain(),&gc.orBlob, &gc.result);
+ GCPROTECT_END();
+
+ VALIDATEOBJECTREF(gc.result);
+
+ return gc.result;
+}
+
+// Copy an object to the given appdomain from the current appdomain.
+OBJECTREF AppDomainHelper::CrossContextCopyTo(IN AppDomain *pDomain,
+ IN OBJECTREF *orObject) // Object must be GC protected
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(orObject!=NULL);
+ PRECONDITION(IsProtectedByGCFrame(orObject));
+ PRECONDITION(pDomain!=NULL);
+ PRECONDITION(pDomain != GetAppDomain());
+ }
+ CONTRACTL_END;
+
+ VALIDATEOBJECTREF(*orObject);
+
+ struct _gc {
+ U1ARRAYREF orBlob;
+ OBJECTREF result;
+ } gc;
+ ZeroMemory(&gc, sizeof(gc));
+
+ GCPROTECT_BEGIN(gc);
+ AppDomainHelper::MarshalObject(orObject, &gc.orBlob);
+ AppDomainHelper::UnmarshalObject(pDomain, &gc.orBlob, &gc.result);
+ GCPROTECT_END();
+
+ VALIDATEOBJECTREF(gc.result);
+
+ return gc.result;
+}
+
+#endif // FEATURE_REMOTING
+