df79978f00d5895eb5c4fe56702c33849238d564
[mono.git] / mcs / class / referencesource / System.Runtime.Serialization / System / Runtime / Serialization / SurrogateDataContract.cs
1 //-----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //-----------------------------------------------------------------------------
4 namespace System.Runtime.Serialization
5 {
6     using System;
7     using System.Security;
8     using System.Security.Permissions;
9     using System.Runtime.CompilerServices;
10
11 #if USE_REFEMIT
12     public sealed class SurrogateDataContract : DataContract
13 #else
14     internal sealed class SurrogateDataContract : DataContract
15 #endif
16     {
17         [Fx.Tag.SecurityNote(Critical = "Holds instance of CriticalHelper which keeps state that is cached statically for serialization."
18             + " Static fields are marked SecurityCritical or readonly to prevent data from being modified or leaked to other components in appdomain.")]
19         [SecurityCritical]
20         SurrogateDataContractCriticalHelper helper;
21
22         [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.",
23             Safe = "Doesn't leak anything.")]
24         [SecuritySafeCritical]
25         internal SurrogateDataContract(Type type, ISerializationSurrogate serializationSurrogate)
26             : base(new SurrogateDataContractCriticalHelper(type, serializationSurrogate))
27         {
28             helper = base.Helper as SurrogateDataContractCriticalHelper;
29         }
30
31         internal ISerializationSurrogate SerializationSurrogate
32         {
33             [Fx.Tag.SecurityNote(Critical = "Fetches the critical serializationSurrogate property.",
34                 Safe = "serializationSurrogate only needs to be protected for write.")]
35             [SecuritySafeCritical]
36             get { return helper.SerializationSurrogate; }
37         }
38
39         public override void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context)
40         {
41             SerializationInfo serInfo = new SerializationInfo(UnderlyingType, XmlObjectSerializer.FormatterConverter, !context.UnsafeTypeForwardingEnabled);
42             SerializationSurrogateGetObjectData(obj, serInfo, context.GetStreamingContext());
43             context.WriteSerializationInfo(xmlWriter, UnderlyingType, serInfo);
44         }
45
46         [Fx.Tag.SecurityNote(Critical = "Calls the critical methods of ISurrogateSelector", Safe = "Demands for FullTrust")]
47         [SecuritySafeCritical]
48         [PermissionSet(SecurityAction.Demand, Unrestricted = true)]
49         [MethodImpl(MethodImplOptions.NoInlining)]
50         object SerializationSurrogateSetObjectData(object obj, SerializationInfo serInfo, StreamingContext context)
51         {
52             return SerializationSurrogate.SetObjectData(obj, serInfo, context, null);
53         }
54
55         [Fx.Tag.SecurityNote(Critical = "Calls the critical methods of IObjectReference", Safe = "Demands for FullTrust")]
56         [SecuritySafeCritical]
57         [PermissionSet(SecurityAction.Demand, Unrestricted = true)]
58         [MethodImpl(MethodImplOptions.NoInlining)]
59         internal static object GetRealObject(IObjectReference obj, StreamingContext context)
60         {
61             return obj.GetRealObject(context);
62         }
63
64         [Fx.Tag.SecurityNote(Critical = "Calls the critical methods of FormatterServices", Safe = "Demands for FullTrust")]
65         [SecuritySafeCritical]
66         [PermissionSet(SecurityAction.Demand, Unrestricted = true)]
67         [MethodImpl(MethodImplOptions.NoInlining)]
68         object GetUninitializedObject(Type objType)
69         {
70             return FormatterServices.GetUninitializedObject(objType);
71         }
72
73         [Fx.Tag.SecurityNote(Critical = "Calls the critical methods of ISerializationSurrogate", Safe = "Demands for FullTrust")]
74         [SecuritySafeCritical]
75         [PermissionSet(SecurityAction.Demand, Unrestricted = true)]
76         [MethodImpl(MethodImplOptions.NoInlining)]
77         void SerializationSurrogateGetObjectData(object obj, SerializationInfo serInfo, StreamingContext context)
78         {
79             SerializationSurrogate.GetObjectData(obj, serInfo, context);
80         }
81
82         public override object ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
83         {
84             xmlReader.Read();
85             Type objType = UnderlyingType;
86             object obj = objType.IsArray ? Array.CreateInstance(objType.GetElementType(), 0) : GetUninitializedObject(objType);
87             context.AddNewObject(obj);
88             string objectId = context.GetObjectId();
89             SerializationInfo serInfo = context.ReadSerializationInfo(xmlReader, objType);
90             object newObj = SerializationSurrogateSetObjectData(obj, serInfo, context.GetStreamingContext());
91             if (newObj == null)
92                 newObj = obj;
93             if (newObj is IDeserializationCallback)
94                 ((IDeserializationCallback)newObj).OnDeserialization(null);
95             if (newObj is IObjectReference)
96                 newObj = GetRealObject((IObjectReference)newObj, context.GetStreamingContext());
97             context.ReplaceDeserializedObject(objectId, obj, newObj);
98             xmlReader.ReadEndElement();
99             return newObj;
100         }
101
102         [Fx.Tag.SecurityNote(Critical = "Holds all state used for for (de)serializing with ISerializationSurrogate."
103             + " Since it accesses data on the base type that is cached statically, we lock down access to it.")]
104         [SecurityCritical(SecurityCriticalScope.Everything)]
105         class SurrogateDataContractCriticalHelper : DataContract.DataContractCriticalHelper
106         {
107             ISerializationSurrogate serializationSurrogate;
108
109             internal SurrogateDataContractCriticalHelper(Type type, ISerializationSurrogate serializationSurrogate)
110                 : base(type)
111             {
112                 this.serializationSurrogate = serializationSurrogate;
113                 string name, ns;
114                 DataContract.GetDefaultStableName(DataContract.GetClrTypeFullName(type), out name, out ns);
115                 SetDataContractName(CreateQualifiedName(name, ns));
116             }
117
118             internal ISerializationSurrogate SerializationSurrogate
119             {
120                 get { return serializationSurrogate; }
121             }
122         }
123     }
124 }
125