Initial commit
[mono.git] / mcs / class / referencesource / mscorlib / system / runtime / serialization / formatters / binary / binaryobjectreader.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 /*============================================================
7  **
8  ** Class: ObjectReader
9  **
10  **
11  ** Purpose: DeSerializes Binary Wire format
12  **
13  **
14  ===========================================================*/
15
16 namespace System.Runtime.Serialization.Formatters.Binary {
17
18     using System;
19     using System.Globalization;
20     using System.IO;
21     using System.Reflection;
22     using System.Collections;
23     using System.Text;
24     using System.Runtime.Remoting;
25     using System.Runtime.Remoting.Messaging;
26     using System.Runtime.Serialization;
27     using System.Security.Permissions;
28     using System.Security;
29     using System.Diagnostics;
30     using System.Resources;
31     using System.Runtime.CompilerServices;
32     using System.Diagnostics.Contracts;
33     using StackCrawlMark = System.Threading.StackCrawlMark;
34
35     internal sealed class ObjectReader
36     {
37
38         // System.Serializer information
39         internal Stream m_stream;
40         internal ISurrogateSelector m_surrogates;
41         internal StreamingContext m_context;
42         internal ObjectManager m_objectManager;
43         internal InternalFE formatterEnums;
44         internal SerializationBinder m_binder;
45
46         // Top object and headers
47         internal long topId;
48         internal bool bSimpleAssembly = false;
49         internal Object handlerObject;
50         internal Object m_topObject;
51         internal Header[] headers;
52         internal HeaderHandler handler;
53         internal SerObjectInfoInit serObjectInfoInit;
54         internal IFormatterConverter m_formatterConverter;
55
56         // Stack of Object ParseRecords
57         internal SerStack stack;
58
59         // ValueType Fixup Stack
60         private SerStack valueFixupStack;
61
62         // Cross AppDomain
63         internal Object[] crossAppDomainArray; //Set by the BinaryFormatter
64
65         //MethodCall and MethodReturn are handled special for perf reasons
66         private bool bFullDeserialization;
67 #if FEATURE_REMOTING        
68         private bool bMethodCall;
69         private bool bMethodReturn;
70         private BinaryMethodCall binaryMethodCall;
71         private BinaryMethodReturn binaryMethodReturn;
72         private bool bIsCrossAppDomain;
73 #endif        
74
75         private static FileIOPermission sfileIOPermission = new FileIOPermission(PermissionState.Unrestricted);
76         
77         private SerStack ValueFixupStack
78         {
79             get {
80                 if (valueFixupStack == null)
81                     valueFixupStack = new SerStack("ValueType Fixup Stack");
82                 return valueFixupStack;
83             }
84         }
85
86         internal Object TopObject{
87             get {
88                 return m_topObject;
89             }
90             set {
91                 m_topObject = value;
92                 if (m_objectManager != null)
93                     m_objectManager.TopObject = value;
94             }
95         }
96 #if FEATURE_REMOTING        
97         internal void SetMethodCall(BinaryMethodCall binaryMethodCall)
98         {
99             bMethodCall = true;
100             this.binaryMethodCall = binaryMethodCall;
101         }
102
103         internal void SetMethodReturn(BinaryMethodReturn binaryMethodReturn)
104         {
105             bMethodReturn = true;
106             this.binaryMethodReturn = binaryMethodReturn;
107         }
108 #endif
109
110         internal ObjectReader(Stream stream, ISurrogateSelector selector, StreamingContext context, InternalFE formatterEnums, SerializationBinder binder)
111         {
112             if (stream == null)
113             {
114                 throw new ArgumentNullException("stream", Environment.GetResourceString("ArgumentNull_Stream"));
115             }
116             Contract.EndContractBlock();
117
118             SerTrace.Log(this, "Constructor ISurrogateSelector ", ((selector == null) ? "null selector " : "selector present"));
119
120             m_stream=stream;
121             m_surrogates = selector;
122             m_context = context;
123             m_binder =  binder;
124
125 #if !FEATURE_PAL && FEATURE_SERIALIZATION
126             // This is a hack to allow us to write a type-limiting deserializer
127             // when we know exactly what type to expect at the head of the 
128             // object graph.
129             if (m_binder != null) {
130                 ResourceReader.TypeLimitingDeserializationBinder tldBinder = m_binder as ResourceReader.TypeLimitingDeserializationBinder;
131                 if (tldBinder != null)
132                     tldBinder.ObjectReader = this;
133             }
134 #endif // !FEATURE_PAL && FEATURE_SERIALIZATION
135
136             this.formatterEnums = formatterEnums;
137
138             //SerTrace.Log( this, "Constructor formatterEnums.FEtopObject ",formatterEnums.FEtopObject);
139
140         }
141
142 #if FEATURE_REMOTING
143         [System.Security.SecurityCritical]  // auto-generated
144         internal Object Deserialize(HeaderHandler handler, __BinaryParser serParser, bool fCheck, bool isCrossAppDomain, IMethodCallMessage methodCallMessage) {
145             if (serParser == null)
146                 throw new ArgumentNullException("serParser", Environment.GetResourceString("ArgumentNull_WithParamName", serParser));
147             Contract.EndContractBlock();
148
149 #if _DEBUG
150             SerTrace.Log( this, "Deserialize Entry handler", handler);
151 #endif
152             bFullDeserialization = false;
153             TopObject = null;
154             topId = 0;
155 #if FEATURE_REMOTING
156             bMethodCall = false;
157             bMethodReturn = false;
158             bIsCrossAppDomain = isCrossAppDomain;
159 #endif
160             bSimpleAssembly =  (formatterEnums.FEassemblyFormat == FormatterAssemblyStyle.Simple);
161
162             if (fCheck)
163             {
164                 CodeAccessPermission.Demand(PermissionType.SecuritySerialization);
165             }
166
167             this.handler = handler;
168
169             Contract.Assert(!bFullDeserialization, "we just set bFullDeserialization to false");
170
171             // Will call back to ParseObject, ParseHeader for each object found
172             serParser.Run();
173
174 #if _DEBUG
175             SerTrace.Log( this, "Deserialize Finished Parsing DoFixups");
176 #endif
177
178             if (bFullDeserialization)
179                 m_objectManager.DoFixups();
180
181
182 #if FEATURE_REMOTING
183             if (!bMethodCall && !bMethodReturn)
184 #endif                
185             {
186                 if (TopObject == null)
187                     throw new SerializationException(Environment.GetResourceString("Serialization_TopObject"));
188
189                 //if TopObject has a surrogate then the actual object may be changed during special fixup
190                 //So refresh it using topID.
191                 if (HasSurrogate(TopObject.GetType())  && topId != 0)//Not yet resolved
192                     TopObject = m_objectManager.GetObject(topId);
193
194                 if (TopObject is IObjectReference)
195                 {
196                     TopObject = ((IObjectReference)TopObject).GetRealObject(m_context);
197                 }
198             }
199
200             SerTrace.Log( this, "Deserialize Exit ",TopObject);
201
202             if (bFullDeserialization)
203             {
204                 m_objectManager.RaiseDeserializationEvent(); // This will raise both IDeserialization and [OnDeserialized] events
205             }                
206
207             // Return the headers if there is a handler
208             if (handler != null)
209             {
210                 handlerObject = handler(headers);
211             }
212 #if FEATURE_REMOTING
213             if (bMethodCall)
214             {
215                 Object[] methodCallArray = TopObject as Object[];
216                 TopObject = binaryMethodCall.ReadArray(methodCallArray, handlerObject);
217             }
218             else if (bMethodReturn)
219             {
220                 Object[] methodReturnArray = TopObject as Object[];
221                 TopObject = binaryMethodReturn.ReadArray(methodReturnArray, methodCallMessage, handlerObject);
222             }
223 #endif
224             return TopObject;
225         }
226 #endif       
227
228 #if !FEATURE_REMOTING
229         internal Object Deserialize(HeaderHandler handler, __BinaryParser serParser, bool fCheck)
230         {
231             if (serParser == null)
232                 throw new ArgumentNullException("serParser", Environment.GetResourceString("ArgumentNull_WithParamName", serParser));
233             Contract.EndContractBlock();
234
235 #if _DEBUG
236             SerTrace.Log( this, "Deserialize Entry handler", handler);
237 #endif
238             bFullDeserialization = false;
239             TopObject = null;
240             topId = 0;
241 #if FEATURE_REMOTING
242             bMethodCall = false;
243             bMethodReturn = false;
244             bIsCrossAppDomain = isCrossAppDomain;
245 #endif
246             bSimpleAssembly =  (formatterEnums.FEassemblyFormat == FormatterAssemblyStyle.Simple);
247
248             if (fCheck)
249             {
250                 CodeAccessPermission.Demand(PermissionType.SecuritySerialization);
251             }
252
253             this.handler = handler;
254
255
256             if (bFullDeserialization)
257             {
258                 // Reinitialize
259 #if FEATURE_REMOTING
260                 m_objectManager = new ObjectManager(m_surrogates, m_context, false, bIsCrossAppDomain);
261 #else
262                 m_objectManager = new ObjectManager(m_surrogates, m_context, false, false);
263 #endif
264                 serObjectInfoInit = new SerObjectInfoInit();
265             }
266
267             // Will call back to ParseObject, ParseHeader for each object found
268             serParser.Run();
269
270 #if _DEBUG
271             SerTrace.Log( this, "Deserialize Finished Parsing DoFixups");
272 #endif
273
274             if (bFullDeserialization)
275                 m_objectManager.DoFixups();
276
277
278 #if FEATURE_REMOTING
279             if (!bMethodCall && !bMethodReturn)
280 #endif                
281             {
282                 if (TopObject == null)
283                     throw new SerializationException(Environment.GetResourceString("Serialization_TopObject"));
284
285                 //if TopObject has a surrogate then the actual object may be changed during special fixup
286                 //So refresh it using topID.
287                 if (HasSurrogate(TopObject.GetType())  && topId != 0)//Not yet resolved
288                     TopObject = m_objectManager.GetObject(topId);
289
290                 if (TopObject is IObjectReference)
291                 {
292                     TopObject = ((IObjectReference)TopObject).GetRealObject(m_context);
293                 }
294             }
295
296             SerTrace.Log( this, "Deserialize Exit ",TopObject);
297
298             if (bFullDeserialization)
299             {
300                 m_objectManager.RaiseDeserializationEvent(); // This will raise both IDeserialization and [OnDeserialized] events
301             }                
302
303             // Return the headers if there is a handler
304             if (handler != null)
305             {
306                 handlerObject = handler(headers);
307             }
308 #if FEATURE_REMOTING
309             if (bMethodCall)
310             {
311                 Object[] methodCallArray = TopObject as Object[];
312                 TopObject = binaryMethodCall.ReadArray(methodCallArray, handlerObject);
313             }
314             else if (bMethodReturn)
315             {
316                 Object[] methodReturnArray = TopObject as Object[];
317                 TopObject = binaryMethodReturn.ReadArray(methodReturnArray, methodCallMessage, handlerObject);
318             }
319 #endif
320             return TopObject;
321         }
322 #endif
323
324         [System.Security.SecurityCritical]  // auto-generated
325         private bool HasSurrogate(Type t){
326             if (m_surrogates == null)
327                 return false;
328             ISurrogateSelector notUsed;
329             return m_surrogates.GetSurrogate(t, m_context, out notUsed) != null;
330         }
331
332         [System.Security.SecurityCritical]  // auto-generated
333         private void CheckSerializable(Type t)
334         {
335             if (!t.IsSerializable && !HasSurrogate(t))
336                 throw new SerializationException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Serialization_NonSerType"), 
337                                                                      t.FullName, t.Assembly.FullName));
338         }
339
340         [System.Security.SecurityCritical]  // auto-generated
341         private void InitFullDeserialization()
342         {
343             bFullDeserialization = true;
344             stack = new SerStack("ObjectReader Object Stack");
345 #if FEATURE_REMOTING
346             m_objectManager = new ObjectManager(m_surrogates, m_context, false, bIsCrossAppDomain);
347 #else
348             m_objectManager = new ObjectManager(m_surrogates, m_context, false, false);
349 #endif
350             if (m_formatterConverter == null)
351                 m_formatterConverter = new FormatterConverter();
352         }
353
354
355         internal Object CrossAppDomainArray(int index)
356         {
357             Contract.Assert((index < crossAppDomainArray.Length),
358                              "[System.Runtime.Serialization.Formatters.BinaryObjectReader index out of range for CrossAppDomainArray]");
359             return crossAppDomainArray[index];
360         }
361
362         [System.Security.SecurityCritical]  // auto-generated
363         internal ReadObjectInfo CreateReadObjectInfo(Type objectType)
364         {
365             return ReadObjectInfo.Create(objectType, m_surrogates, m_context, m_objectManager, serObjectInfoInit, m_formatterConverter, bSimpleAssembly);
366         }
367
368         [System.Security.SecurityCritical]  // auto-generated
369         internal ReadObjectInfo CreateReadObjectInfo(Type objectType, String[] memberNames, Type[] memberTypes)
370         {
371             return ReadObjectInfo.Create(objectType, memberNames, memberTypes, m_surrogates, m_context, m_objectManager, serObjectInfoInit, m_formatterConverter, bSimpleAssembly);
372         }
373
374
375         // Main Parse routine, called by the XML Parse Handlers in XMLParser and also called internally to
376         [System.Security.SecurityCritical]  // auto-generated
377         internal void Parse(ParseRecord pr)
378         {
379 #if _DEBUG
380             SerTrace.Log( this, "Parse");
381             stack.Dump();
382             pr.Dump();
383 #endif
384
385             switch (pr.PRparseTypeEnum)
386             {
387                 case InternalParseTypeE.SerializedStreamHeader:
388                     ParseSerializedStreamHeader(pr);
389                     break;
390                 case InternalParseTypeE.SerializedStreamHeaderEnd:
391                     ParseSerializedStreamHeaderEnd(pr);
392                     break;                  
393                 case InternalParseTypeE.Object:
394                     ParseObject(pr);
395                     break;
396                 case InternalParseTypeE.ObjectEnd:
397                     ParseObjectEnd(pr);
398                     break;
399                 case InternalParseTypeE.Member:
400                     ParseMember(pr);
401                     break;
402                 case InternalParseTypeE.MemberEnd:
403                     ParseMemberEnd(pr);
404                     break;
405                 case InternalParseTypeE.Body:
406                 case InternalParseTypeE.BodyEnd:
407                 case InternalParseTypeE.Envelope:
408                 case InternalParseTypeE.EnvelopeEnd:
409                     break;
410                 case InternalParseTypeE.Empty:
411                 default:
412                     throw new SerializationException(Environment.GetResourceString("Serialization_XMLElement", pr.PRname));                  
413
414             }
415         }
416
417
418         // Styled ParseError output
419         private void ParseError(ParseRecord processing, ParseRecord onStack)
420         {
421 #if _DEBUG
422             SerTrace.Log( this, " ParseError ",processing," ",onStack);
423 #endif
424             throw new SerializationException(Environment.GetResourceString("Serialization_ParseError",onStack.PRname+" "+((Enum)onStack.PRparseTypeEnum) + " "+processing.PRname+" "+((Enum)processing.PRparseTypeEnum)));                               
425         }
426
427         // Parse the SerializedStreamHeader element. This is the first element in the stream if present
428         private void ParseSerializedStreamHeader(ParseRecord pr)
429         {
430 #if _DEBUG
431             SerTrace.Log( this, "SerializedHeader ",pr);
432 #endif
433             stack.Push(pr);
434         }
435
436         // Parse the SerializedStreamHeader end element. This is the last element in the stream if present
437         private void ParseSerializedStreamHeaderEnd(ParseRecord pr)
438         {
439 #if _DEBUG
440             SerTrace.Log( this, "SerializedHeaderEnd ",pr);
441 #endif
442             stack.Pop();
443         }
444
445 #if FEATURE_REMOTING
446         private bool IsRemoting {
447             get {
448                 //return (m_context.State & (StreamingContextStates.Persistence|StreamingContextStates.File|StreamingContextStates.Clone)) == 0;
449                 return (bMethodCall || bMethodReturn);
450             }
451         }
452
453          [System.Security.SecurityCritical]  // auto-generated
454          internal void CheckSecurity(ParseRecord pr)
455          {
456             InternalST.SoapAssert(pr!=null, "[BinaryObjectReader.CheckSecurity]pr!=null");
457             Type t = pr.PRdtType;
458             if ((object)t != null){
459                 if( IsRemoting){
460                     if (typeof(MarshalByRefObject).IsAssignableFrom(t))
461                         throw new ArgumentException(Environment.GetResourceString("Serialization_MBRAsMBV", t.FullName));
462                     FormatterServices.CheckTypeSecurity(t, formatterEnums.FEsecurityLevel);
463                 }
464             }
465         }
466 #endif
467
468         // New object encountered in stream
469         [System.Security.SecurityCritical]  // auto-generated
470         private void ParseObject(ParseRecord pr)
471         {
472 #if _DEBUG
473             SerTrace.Log( this, "ParseObject Entry ");
474 #endif
475
476             if (!bFullDeserialization)
477                 InitFullDeserialization();
478
479             if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
480                 topId = pr.PRobjectId;
481
482             if (pr.PRparseTypeEnum == InternalParseTypeE.Object)
483             {
484                     stack.Push(pr); // Nested objects member names are already on stack
485             }
486
487             if (pr.PRobjectTypeEnum == InternalObjectTypeE.Array)
488             {
489                 ParseArray(pr);
490 #if _DEBUG
491                 SerTrace.Log( this, "ParseObject Exit, ParseArray ");
492 #endif
493                 return;
494             }
495
496             // If the Type is null, this means we have a typeload issue
497             // mark the object with TypeLoadExceptionHolder
498             if ((object)pr.PRdtType == null)
499             {
500                 pr.PRnewObj = new TypeLoadExceptionHolder(pr.PRkeyDt);
501                 return;
502             }
503             
504             if (Object.ReferenceEquals(pr.PRdtType, Converter.typeofString))
505             {
506                 // String as a top level object
507                 if (pr.PRvalue != null)
508                 {
509                     pr.PRnewObj = pr.PRvalue;
510                     if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
511                     {
512 #if _DEBUG
513                         SerTrace.Log( this, "ParseObject String as top level, Top Object Resolved");
514 #endif
515                         TopObject = pr.PRnewObj;
516                         //stack.Pop();
517                         return;
518                     }
519                     else
520                     {
521 #if _DEBUG
522                         SerTrace.Log( this, "ParseObject  String as an object");
523 #endif
524                         stack.Pop();                        
525                         RegisterObject(pr.PRnewObj, pr, (ParseRecord)stack.Peek());                         
526                         return;
527                     }
528                 }
529                 else
530                 {
531                     // xml Doesn't have the value until later
532                     return;
533                 }
534             }
535             else {
536                     CheckSerializable(pr.PRdtType);
537 #if FEATURE_REMOTING
538                     if (IsRemoting && formatterEnums.FEsecurityLevel != TypeFilterLevel.Full)
539                         pr.PRnewObj = FormatterServices.GetSafeUninitializedObject(pr.PRdtType);                                 
540                     else
541 #endif                        
542                         pr.PRnewObj = FormatterServices.GetUninitializedObject(pr.PRdtType);            
543
544                     // Run the OnDeserializing methods
545                     m_objectManager.RaiseOnDeserializingEvent(pr.PRnewObj);
546             }
547
548             if (pr.PRnewObj == null)
549                 throw new SerializationException(Environment.GetResourceString("Serialization_TopObjectInstantiate",pr.PRdtType));
550
551             if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
552             {
553 #if _DEBUG
554                 SerTrace.Log( this, "ParseObject  Top Object Resolved ",pr.PRnewObj.GetType());
555 #endif
556                 TopObject = pr.PRnewObj;
557             }
558
559             if (pr.PRobjectInfo == null)
560                 pr.PRobjectInfo = ReadObjectInfo.Create(pr.PRdtType, m_surrogates, m_context, m_objectManager, serObjectInfoInit, m_formatterConverter, bSimpleAssembly);
561
562 #if FEATURE_REMOTING
563             CheckSecurity(pr);
564 #endif
565
566 #if _DEBUG
567             SerTrace.Log( this, "ParseObject Exit ");       
568 #endif
569         }
570
571         // End of object encountered in stream
572         [System.Security.SecurityCritical]  // auto-generated
573         private void ParseObjectEnd(ParseRecord pr)
574         {
575 #if _DEBUG
576             SerTrace.Log( this, "ParseObjectEnd Entry ",pr.Trace());
577 #endif
578             ParseRecord objectPr = (ParseRecord)stack.Peek();
579             if (objectPr == null)
580                 objectPr = pr;
581
582             //Contract.Assert(objectPr != null, "[System.Runtime.Serialization.Formatters.ParseObjectEnd]objectPr != null");
583
584 #if _DEBUG
585             SerTrace.Log( this, "ParseObjectEnd objectPr ",objectPr.Trace());
586 #endif
587
588             if (objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top)
589             {
590 #if _DEBUG
591                 SerTrace.Log( this, "ParseObjectEnd Top Object dtType ",objectPr.PRdtType);
592 #endif
593                 if (Object.ReferenceEquals(objectPr.PRdtType, Converter.typeofString))
594                 {
595 #if _DEBUG
596                     SerTrace.Log( this, "ParseObjectEnd Top String");
597 #endif
598                     objectPr.PRnewObj = objectPr.PRvalue;
599                     TopObject = objectPr.PRnewObj;
600                     return;
601                 }
602             }
603
604             stack.Pop();
605             ParseRecord parentPr = (ParseRecord)stack.Peek();
606
607             if (objectPr.PRnewObj == null)
608                 return;
609
610             if (objectPr.PRobjectTypeEnum == InternalObjectTypeE.Array)
611             {
612                 if (objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top)
613                 {
614 #if _DEBUG
615                     SerTrace.Log( this, "ParseObjectEnd  Top Object (Array) Resolved");
616 #endif
617                     TopObject = objectPr.PRnewObj;
618                 }
619
620 #if _DEBUG
621                 SerTrace.Log( this, "ParseArray  RegisterObject ",objectPr.PRobjectId," ",objectPr.PRnewObj.GetType());
622 #endif
623                 RegisterObject(objectPr.PRnewObj, objectPr, parentPr);                  
624
625                 return;
626             }
627
628             objectPr.PRobjectInfo.PopulateObjectMembers(objectPr.PRnewObj, objectPr.PRmemberData);
629
630             // Registration is after object is populated
631             if ((!objectPr.PRisRegistered) && (objectPr.PRobjectId > 0)) 
632             {
633 #if _DEBUG
634                 SerTrace.Log( this, "ParseObject Register Object ",objectPr.PRobjectId," ",objectPr.PRnewObj.GetType());
635 #endif
636                 RegisterObject(objectPr.PRnewObj, objectPr, parentPr);
637             }
638             
639             if (objectPr.PRisValueTypeFixup)
640             {
641 #if _DEBUG
642                 SerTrace.Log( this, "ParseObjectEnd  ValueTypeFixup ",objectPr.PRnewObj.GetType());
643 #endif
644                 ValueFixup fixup = (ValueFixup)ValueFixupStack.Pop(); //Value fixup
645                 fixup.Fixup(objectPr, parentPr);  // Value fixup
646
647             }
648
649             if (objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top)
650             {
651 #if _DEBUG
652                 SerTrace.Log( this, "ParseObjectEnd  Top Object Resolved ",objectPr.PRnewObj.GetType());
653 #endif
654                 TopObject = objectPr.PRnewObj;
655             }
656
657             objectPr.PRobjectInfo.ObjectEnd();
658
659 #if _DEBUG
660             SerTrace.Log( this, "ParseObjectEnd  Exit ",objectPr.PRnewObj.GetType()," id: ",objectPr.PRobjectId);       
661 #endif
662         }
663
664
665
666         // Array object encountered in stream
667         [System.Security.SecurityCritical]  // auto-generated
668         private void ParseArray(ParseRecord pr)
669         {
670             SerTrace.Log( this, "ParseArray Entry");
671
672             long genId = pr.PRobjectId;
673
674             if (pr.PRarrayTypeEnum == InternalArrayTypeE.Base64)
675             {
676                 SerTrace.Log( this, "ParseArray bin.base64 ",pr.PRvalue.Length," ",pr.PRvalue);
677                 // ByteArray
678                 if (pr.PRvalue.Length > 0)
679                     pr.PRnewObj = Convert.FromBase64String(pr.PRvalue);
680                 else
681                     pr.PRnewObj = new Byte[0];
682
683                 if (stack.Peek() == pr)
684                 {
685                     SerTrace.Log( this, "ParseArray, bin.base64 has been stacked");
686                     stack.Pop();
687                 }
688                 if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
689         {  
690                     TopObject = pr.PRnewObj;
691         }
692
693                 ParseRecord parentPr = (ParseRecord)stack.Peek();                                           
694
695                 // Base64 can be registered at this point because it is populated
696                 SerTrace.Log( this, "ParseArray  RegisterObject ",pr.PRobjectId," ",pr.PRnewObj.GetType());
697                 RegisterObject(pr.PRnewObj, pr, parentPr);
698
699             }
700             else if ((pr.PRnewObj != null) && Converter.IsWriteAsByteArray(pr.PRarrayElementTypeCode))
701             {
702                 // Primtive typed Array has already been read
703                 if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
704         {       
705                     TopObject = pr.PRnewObj;
706         }
707
708                 ParseRecord parentPr = (ParseRecord)stack.Peek();                                           
709
710                 // Primitive typed array can be registered at this point because it is populated
711                 SerTrace.Log( this, "ParseArray  RegisterObject ",pr.PRobjectId," ",pr.PRnewObj.GetType());
712                 RegisterObject(pr.PRnewObj, pr, parentPr);
713             }
714             else if ((pr.PRarrayTypeEnum == InternalArrayTypeE.Jagged) || (pr.PRarrayTypeEnum == InternalArrayTypeE.Single))
715             {
716                 // Multidimensional jagged array or single array
717                 SerTrace.Log( this, "ParseArray Before Jagged,Simple create ",pr.PRarrayElementType," ",pr.PRlengthA[0]);
718                 bool bCouldBeValueType = true;
719                 if ((pr.PRlowerBoundA == null) || (pr.PRlowerBoundA[0] == 0))
720                 {
721                     if (Object.ReferenceEquals(pr.PRarrayElementType, Converter.typeofString))
722                     {
723                         pr.PRobjectA = new String[pr.PRlengthA[0]];
724                         pr.PRnewObj = pr.PRobjectA;
725                         bCouldBeValueType = false;
726                     }
727                     else if (Object.ReferenceEquals(pr.PRarrayElementType, Converter.typeofObject))
728                     {
729                         pr.PRobjectA = new Object[pr.PRlengthA[0]];
730                         pr.PRnewObj = pr.PRobjectA;
731                         bCouldBeValueType = false;
732                     }
733                     else if ((object)pr.PRarrayElementType != null) {
734                         pr.PRnewObj = Array.UnsafeCreateInstance(pr.PRarrayElementType, pr.PRlengthA[0]);
735                     }
736                     pr.PRisLowerBound = false;
737                 }
738                 else
739                 {
740                     if ((object)pr.PRarrayElementType != null) {
741                         pr.PRnewObj = Array.UnsafeCreateInstance(pr.PRarrayElementType, pr.PRlengthA, pr.PRlowerBoundA);
742                     }
743                     pr.PRisLowerBound = true;
744                 }
745
746                 if (pr.PRarrayTypeEnum == InternalArrayTypeE.Single)
747                 {
748                     if (!pr.PRisLowerBound && (Converter.IsWriteAsByteArray(pr.PRarrayElementTypeCode)))
749                     {
750                         pr.PRprimitiveArray = new PrimitiveArray(pr.PRarrayElementTypeCode, (Array)pr.PRnewObj);
751                     }
752                     else if (bCouldBeValueType && (object)pr.PRarrayElementType != null)
753                     {
754                         if (!pr.PRarrayElementType.IsValueType && !pr.PRisLowerBound)
755                             pr.PRobjectA = (Object[])pr.PRnewObj;
756                     }
757                 }
758
759                 SerTrace.Log( this, "ParseArray Jagged,Simple Array ",pr.PRnewObj.GetType());
760
761                 // For binary, headers comes in as an array of header objects
762                 if (pr.PRobjectPositionEnum == InternalObjectPositionE.Headers)
763                 {
764                     SerTrace.Log( this, "ParseArray header array");
765                     headers = (Header[])pr.PRnewObj;
766                 }
767
768                 pr.PRindexMap = new int[1];
769
770             }
771             else if (pr.PRarrayTypeEnum == InternalArrayTypeE.Rectangular)
772             {
773                 // Rectangle array
774
775                 pr.PRisLowerBound = false;
776                 if (pr.PRlowerBoundA != null)
777                 {
778                     for (int i=0; i<pr.PRrank; i++)
779                     {
780                         if (pr.PRlowerBoundA[i] != 0)
781                             pr.PRisLowerBound = true;
782                     }
783                 }
784
785                 if ((object)pr.PRarrayElementType != null){
786                     if (!pr.PRisLowerBound)
787                         pr.PRnewObj = Array.UnsafeCreateInstance(pr.PRarrayElementType, pr.PRlengthA);
788                     else
789                         pr.PRnewObj = Array.UnsafeCreateInstance(pr.PRarrayElementType, pr.PRlengthA, pr.PRlowerBoundA);
790                 }
791
792                 SerTrace.Log( this, "ParseArray Rectangle Array ",pr.PRnewObj.GetType()," lower Bound ",pr.PRisLowerBound);
793
794                 // Calculate number of items
795                 int sum = 1;
796                 for (int i=0; i<pr.PRrank; i++)
797                 {
798                     sum = sum*pr.PRlengthA[i];
799                 }
800                 pr.PRindexMap = new int[pr.PRrank];
801                 pr.PRrectangularMap = new int[pr.PRrank];
802                 pr.PRlinearlength = sum;
803             }
804             else
805                 throw new SerializationException(Environment.GetResourceString("Serialization_ArrayType",((Enum)pr.PRarrayTypeEnum)));                               
806
807 #if FEATURE_REMOTING
808             CheckSecurity(pr);
809 #endif
810             SerTrace.Log( this, "ParseArray Exit");     
811         }
812
813
814         // Builds a map for each item in an incoming rectangle array. The map specifies where the item is placed in the output Array Object
815
816         private void NextRectangleMap(ParseRecord pr)
817         {
818             // For each invocation, calculate the next rectangular array position
819             // example
820             // indexMap 0 [0,0,0]
821             // indexMap 1 [0,0,1]
822             // indexMap 2 [0,0,2]
823             // indexMap 3 [0,0,3]
824             // indexMap 4 [0,1,0]       
825             for (int irank = pr.PRrank-1; irank>-1; irank--)
826             {
827                 // Find the current or lower dimension which can be incremented.
828                 if (pr.PRrectangularMap[irank] < pr.PRlengthA[irank]-1)
829                 {
830                     // The current dimension is at maximum. Increase the next lower dimension by 1
831                     pr.PRrectangularMap[irank]++;
832                     if (irank < pr.PRrank-1)
833                     {
834                         // The current dimension and higher dimensions are zeroed.
835                         for (int i = irank+1; i<pr.PRrank; i++)
836                             pr.PRrectangularMap[i] = 0;
837                     }
838                     Array.Copy(pr.PRrectangularMap, pr.PRindexMap, pr.PRrank);              
839                     break;                  
840                 }
841
842             }
843         }
844
845
846         // Array object item encountered in stream
847         [System.Security.SecurityCritical]  // auto-generated
848         private void ParseArrayMember(ParseRecord pr)
849         {
850             SerTrace.Log( this, "ParseArrayMember Entry");
851             ParseRecord objectPr = (ParseRecord)stack.Peek();
852
853
854             // Set up for inserting value into correct array position
855             if (objectPr.PRarrayTypeEnum == InternalArrayTypeE.Rectangular)
856             {
857
858                 if (objectPr.PRmemberIndex > 0)
859                     NextRectangleMap(objectPr); // Rectangle array, calculate position in array
860                 if (objectPr.PRisLowerBound)
861                 {
862                     for (int i=0; i<objectPr.PRrank; i++)
863                     {
864             objectPr.PRindexMap[i] = objectPr.PRrectangularMap[i] + objectPr.PRlowerBoundA[i];
865                     }
866                 }
867             }
868             else
869             {
870                 if (!objectPr.PRisLowerBound)
871                 {
872                         objectPr.PRindexMap[0] = objectPr.PRmemberIndex; // Zero based array
873                 }
874                 else
875                     objectPr.PRindexMap[0] = objectPr.PRlowerBoundA[0]+objectPr.PRmemberIndex; // Lower Bound based array
876             }
877             IndexTraceMessage("ParseArrayMember isLowerBound "+objectPr.PRisLowerBound+" indexMap  ", objectPr.PRindexMap);     
878
879             // Set Array element according to type of element
880
881             if (pr.PRmemberValueEnum == InternalMemberValueE.Reference)
882             {
883                 // Object Reference
884
885                 // See if object has already been instantiated
886                 Object refObj = m_objectManager.GetObject(pr.PRidRef);
887                 if (refObj == null)
888                 {
889                     // Object not instantiated
890                     // Array fixup manager
891             IndexTraceMessage("ParseArrayMember Record Fixup  "+objectPr.PRnewObj.GetType(), objectPr.PRindexMap);
892                     int[] fixupIndex = new int[objectPr.PRrank];
893                     Array.Copy(objectPr.PRindexMap, 0, fixupIndex, 0, objectPr.PRrank);
894
895                     SerTrace.Log( this, "ParseArrayMember RecordArrayElementFixup objectId ",objectPr.PRobjectId," idRef ",pr.PRidRef);                                                         
896                     m_objectManager.RecordArrayElementFixup(objectPr.PRobjectId, fixupIndex, pr.PRidRef);
897                 }
898                 else
899                 {
900                     IndexTraceMessage("ParseArrayMember SetValue ObjectReference "+objectPr.PRnewObj.GetType()+" "+refObj, objectPr.PRindexMap);
901                     if (objectPr.PRobjectA != null)
902                         objectPr.PRobjectA[objectPr.PRindexMap[0]] = refObj;
903                     else
904                         ((Array)objectPr.PRnewObj).SetValue(refObj, objectPr.PRindexMap); // Object has been instantiated
905                 }
906             }
907             else if (pr.PRmemberValueEnum == InternalMemberValueE.Nested)
908             {
909                 //Set up dtType for ParseObject
910                 SerTrace.Log( this, "ParseArrayMember Nested ");
911                 if ((object)pr.PRdtType == null)
912                 {
913                     pr.PRdtType = objectPr.PRarrayElementType;
914                 }
915
916                 ParseObject(pr);
917                 stack.Push(pr);
918
919                 if ((object)objectPr.PRarrayElementType != null) {
920                     if ((objectPr.PRarrayElementType.IsValueType) && (pr.PRarrayElementTypeCode == InternalPrimitiveTypeE.Invalid))
921                     {
922 #if _DEBUG                        
923                         SerTrace.Log( "ParseArrayMember ValueType ObjectPr ",objectPr.PRnewObj," index ",objectPr.PRmemberIndex);
924 #endif
925                         pr.PRisValueTypeFixup = true; //Valuefixup
926                         ValueFixupStack.Push(new ValueFixup((Array)objectPr.PRnewObj, objectPr.PRindexMap)); //valuefixup
927                     }
928                     else
929                     {
930 #if _DEBUG                        
931                         SerTrace.Log( "ParseArrayMember SetValue Nested, memberIndex ",objectPr.PRmemberIndex);
932                         IndexTraceMessage("ParseArrayMember SetValue Nested ContainerObject "+objectPr.PRnewObj.GetType()+" "+objectPr.PRnewObj+" item Object "+pr.PRnewObj+" index ", objectPr.PRindexMap);
933
934                         stack.Dump();               
935                         SerTrace.Log( "ParseArrayMember SetValue Nested ContainerObject objectPr ",objectPr.Trace());
936                         SerTrace.Log( "ParseArrayMember SetValue Nested ContainerObject pr ",pr.Trace());
937 #endif
938                         if (objectPr.PRobjectA != null)
939                             objectPr.PRobjectA[objectPr.PRindexMap[0]] = pr.PRnewObj;
940                         else
941                             ((Array)objectPr.PRnewObj).SetValue(pr.PRnewObj, objectPr.PRindexMap);
942                     }
943                 }
944             }
945             else if (pr.PRmemberValueEnum == InternalMemberValueE.InlineValue)
946             {
947                 if ((Object.ReferenceEquals(objectPr.PRarrayElementType, Converter.typeofString)) || (Object.ReferenceEquals(pr.PRdtType, Converter.typeofString)))
948                 {
949                     // String in either a string array, or a string element of an object array
950                     ParseString(pr, objectPr);
951                     IndexTraceMessage("ParseArrayMember SetValue String "+objectPr.PRnewObj.GetType()+" "+pr.PRvalue, objectPr.PRindexMap);
952                     if (objectPr.PRobjectA != null)
953                         objectPr.PRobjectA[objectPr.PRindexMap[0]] = (Object)pr.PRvalue;
954                     else
955                         ((Array)objectPr.PRnewObj).SetValue((Object)pr.PRvalue, objectPr.PRindexMap);
956                 }
957                 else if (objectPr.PRisArrayVariant)
958                 {
959                     // Array of type object
960                     if (pr.PRkeyDt == null)
961                         throw new SerializationException(Environment.GetResourceString("Serialization_ArrayTypeObject"));
962
963                     Object var = null;
964
965                     if (Object.ReferenceEquals(pr.PRdtType, Converter.typeofString))
966                     {
967                         ParseString(pr, objectPr);
968                         var = pr.PRvalue;
969                     }
970                     else if (Object.ReferenceEquals(pr.PRdtTypeCode, InternalPrimitiveTypeE.Invalid))
971                     {
972                         CheckSerializable(pr.PRdtType);
973                         // Not nested and invalid, so it is an empty object
974 #if FEATURE_REMOTING                        
975                         if (IsRemoting && formatterEnums.FEsecurityLevel != TypeFilterLevel.Full)
976                             var = FormatterServices.GetSafeUninitializedObject(pr.PRdtType);                                 
977                         else
978 #endif                            
979                             var = FormatterServices.GetUninitializedObject(pr.PRdtType);
980                     }
981                     else
982                     {
983                         if (pr.PRvarValue != null)
984                             var = pr.PRvarValue;
985                         else
986                             var = Converter.FromString(pr.PRvalue, pr.PRdtTypeCode);
987                     }
988                     IndexTraceMessage("ParseArrayMember SetValue variant or Object "+objectPr.PRnewObj.GetType()+" var "+var+" indexMap ", objectPr.PRindexMap);
989                     if (objectPr.PRobjectA != null)
990                         objectPr.PRobjectA[objectPr.PRindexMap[0]] = var;
991                     else
992                         ((Array)objectPr.PRnewObj).SetValue(var, objectPr.PRindexMap); // Primitive type
993                 }
994                 else
995                 {
996                     // Primitive type
997                     if (objectPr.PRprimitiveArray != null)
998                     {
999                         // Fast path for Soap primitive arrays. Binary was handled in the BinaryParser
1000                         objectPr.PRprimitiveArray.SetValue(pr.PRvalue, objectPr.PRindexMap[0]);
1001                     }
1002                     else
1003                     {
1004
1005                         Object var = null;
1006                         if (pr.PRvarValue != null)
1007                             var = pr.PRvarValue;
1008                         else
1009                             var = Converter.FromString(pr.PRvalue, objectPr.PRarrayElementTypeCode);
1010                         SerTrace.Log( this, "ParseArrayMember SetValue Primitive pr.PRvalue "+var," elementTypeCode ",((Enum)objectPr.PRdtTypeCode));
1011                         IndexTraceMessage("ParseArrayMember SetValue Primitive "+objectPr.PRnewObj.GetType()+" var: "+var+" varType "+var.GetType(), objectPr.PRindexMap);
1012                         if (objectPr.PRobjectA != null)
1013                         {
1014                             SerTrace.Log( this, "ParseArrayMember SetValue Primitive predefined array "+objectPr.PRobjectA.GetType());
1015                             objectPr.PRobjectA[objectPr.PRindexMap[0]] = var;
1016                         }
1017                         else
1018                             ((Array)objectPr.PRnewObj).SetValue(var, objectPr.PRindexMap); // Primitive type   
1019                         SerTrace.Log( this, "ParseArrayMember SetValue Primitive after");
1020                     }
1021                 }
1022             }
1023             else if (pr.PRmemberValueEnum == InternalMemberValueE.Null)
1024             {
1025                 SerTrace.Log( "ParseArrayMember Null item ",pr.PRmemberIndex," nullCount ",pr.PRnullCount);
1026                 objectPr.PRmemberIndex += pr.PRnullCount-1; //also incremented again below
1027             }
1028             else
1029                 ParseError(pr, objectPr);
1030
1031 #if _DEBUG                        
1032             SerTrace.Log( "ParseArrayMember increment memberIndex ",objectPr.PRmemberIndex," ",objectPr.Trace());               
1033 #endif
1034             objectPr.PRmemberIndex++;
1035             SerTrace.Log( "ParseArrayMember Exit");     
1036         }
1037
1038         [System.Security.SecurityCritical]  // auto-generated
1039         private void ParseArrayMemberEnd(ParseRecord pr)
1040         {
1041             SerTrace.Log( this, "ParseArrayMemberEnd");
1042             // If this is a nested array object, then pop the stack
1043             if (pr.PRmemberValueEnum == InternalMemberValueE.Nested)
1044             {
1045                 ParseObjectEnd(pr);
1046             }
1047         }
1048
1049
1050         // Object member encountered in stream
1051         [System.Security.SecurityCritical]  // auto-generated
1052         private void ParseMember(ParseRecord pr)
1053         {
1054             SerTrace.Log( this, "ParseMember Entry ");
1055
1056
1057             ParseRecord objectPr = (ParseRecord)stack.Peek();
1058             String objName = null;
1059             if (objectPr != null)
1060                 objName = objectPr.PRname;
1061
1062 #if _DEBUG                        
1063             SerTrace.Log( this, "ParseMember ",objectPr.PRobjectId," ",pr.PRname);
1064             SerTrace.Log( this, "ParseMember objectPr ",objectPr.Trace());
1065             SerTrace.Log( this, "ParseMember pr ",pr.Trace());
1066 #endif
1067             switch (pr.PRmemberTypeEnum)
1068             {
1069                 case InternalMemberTypeE.Item:
1070                     ParseArrayMember(pr);
1071                     return;
1072                 case InternalMemberTypeE.Field:
1073                     break;
1074             }
1075
1076
1077             //if ((pr.PRdtType == null) && !objectPr.PRobjectInfo.isSi)
1078             if (((object)pr.PRdtType == null) && objectPr.PRobjectInfo.isTyped)
1079             {
1080                 SerTrace.Log( this, "ParseMember pr.PRdtType null and not isSi");
1081                 pr.PRdtType = objectPr.PRobjectInfo.GetType(pr.PRname);
1082
1083                 if ((object)pr.PRdtType != null)
1084                     pr.PRdtTypeCode = Converter.ToCode(pr.PRdtType);
1085             }
1086
1087             if (pr.PRmemberValueEnum == InternalMemberValueE.Null)
1088             {
1089                 // Value is Null
1090                 SerTrace.Log( this, "ParseMember null member: ",pr.PRname);
1091                 SerTrace.Log( this, "AddValue 1");
1092                 objectPr.PRobjectInfo.AddValue(pr.PRname, null, ref objectPr.PRsi, ref objectPr.PRmemberData);
1093             }
1094             else if (pr.PRmemberValueEnum == InternalMemberValueE.Nested)
1095             {
1096                 SerTrace.Log( this, "ParseMember Nested Type member: ",pr.PRname," objectPr.PRnewObj ",objectPr.PRnewObj);
1097                 ParseObject(pr);
1098                 stack.Push(pr);
1099                 SerTrace.Log( this, "AddValue 2 ",pr.PRnewObj," is value type ",pr.PRnewObj.GetType().IsValueType);
1100
1101                 if ((pr.PRobjectInfo != null) && ((object)pr.PRobjectInfo.objectType != null) && (pr.PRobjectInfo.objectType.IsValueType))
1102                 {
1103                     SerTrace.Log( "ParseMember ValueType ObjectPr ",objectPr.PRnewObj," memberName  ",pr.PRname," nested object ",pr.PRnewObj);
1104                     pr.PRisValueTypeFixup = true; //Valuefixup
1105                     ValueFixupStack.Push(new ValueFixup(objectPr.PRnewObj, pr.PRname, objectPr.PRobjectInfo));//valuefixup
1106                 }
1107                 else
1108                 {
1109                     SerTrace.Log( this, "AddValue 2A ");
1110                     objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRnewObj, ref objectPr.PRsi, ref objectPr.PRmemberData);
1111                 }
1112             }
1113             else if (pr.PRmemberValueEnum == InternalMemberValueE.Reference)
1114             {
1115                 SerTrace.Log( this, "ParseMember Reference Type member: ",pr.PRname);           
1116                 // See if object has already been instantiated
1117                 Object refObj = m_objectManager.GetObject(pr.PRidRef);
1118                 if (refObj == null)
1119                 {
1120                     SerTrace.Log( this, "ParseMember RecordFixup: ",pr.PRname);
1121                     SerTrace.Log( this, "AddValue 3");                  
1122                     objectPr.PRobjectInfo.AddValue(pr.PRname, null, ref objectPr.PRsi, ref objectPr.PRmemberData);
1123                     objectPr.PRobjectInfo.RecordFixup(objectPr.PRobjectId, pr.PRname, pr.PRidRef); // Object not instantiated
1124                 }
1125                 else
1126                 {
1127                     SerTrace.Log( this, "ParseMember Referenced Object Known ",pr.PRname," ",refObj);
1128                     SerTrace.Log( this, "AddValue 5");              
1129                     objectPr.PRobjectInfo.AddValue(pr.PRname, refObj, ref objectPr.PRsi, ref objectPr.PRmemberData);
1130                 }
1131             }
1132
1133             else if (pr.PRmemberValueEnum == InternalMemberValueE.InlineValue)
1134             {
1135                 // Primitive type or String
1136                 SerTrace.Log( this, "ParseMember primitive or String member: ",pr.PRname);
1137
1138                 if (Object.ReferenceEquals(pr.PRdtType, Converter.typeofString))
1139                 {
1140                     ParseString(pr, objectPr);
1141                     SerTrace.Log( this, "AddValue 6");              
1142                     objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRvalue, ref objectPr.PRsi, ref objectPr.PRmemberData);  
1143                 }
1144                 else if (pr.PRdtTypeCode == InternalPrimitiveTypeE.Invalid)
1145                 {
1146                     // The member field was an object put the value is Inline either  bin.Base64 or invalid
1147                     if (pr.PRarrayTypeEnum == InternalArrayTypeE.Base64)
1148                     {
1149                         SerTrace.Log( this, "AddValue 7");                  
1150                         objectPr.PRobjectInfo.AddValue(pr.PRname, Convert.FromBase64String(pr.PRvalue), ref objectPr.PRsi, ref objectPr.PRmemberData);                                    
1151                     }
1152                     else if (Object.ReferenceEquals(pr.PRdtType, Converter.typeofObject))
1153                         throw new SerializationException(Environment.GetResourceString("Serialization_TypeMissing", pr.PRname));
1154                     else
1155                     {
1156                         SerTrace.Log( this, "Object Class with no memberInfo data  Member "+pr.PRname+" type "+pr.PRdtType);
1157
1158                         ParseString(pr, objectPr); // Register the object if it has an objectId
1159                         // Object Class with no memberInfo data
1160                         // only special case where AddValue is needed?
1161                         if (Object.ReferenceEquals(pr.PRdtType, Converter.typeofSystemVoid))
1162                         {
1163                             SerTrace.Log( this, "AddValue 9");
1164                             objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRdtType, ref objectPr.PRsi, ref objectPr.PRmemberData);
1165                         }
1166                         else if (objectPr.PRobjectInfo.isSi)
1167                         {
1168                             // ISerializable are added as strings, the conversion to type is done by the
1169                             // ISerializable object
1170                             SerTrace.Log( this, "AddValue 10");
1171                             objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRvalue, ref objectPr.PRsi, ref objectPr.PRmemberData);                          
1172                         }
1173                     }
1174                 }
1175                 else
1176                 {
1177                     Object var = null;
1178                     if (pr.PRvarValue != null)
1179                         var = pr.PRvarValue;
1180                     else
1181                         var = Converter.FromString(pr.PRvalue, pr.PRdtTypeCode);
1182 #if _DEBUG                        
1183                     // Not a string, convert the value
1184                     SerTrace.Log( this, "ParseMember Converting primitive and storing");
1185                     stack.Dump();
1186                     SerTrace.Log( this, "ParseMember pr "+pr.Trace());
1187                     SerTrace.Log( this, "ParseMember objectPr ",objectPr.Trace());
1188
1189                     SerTrace.Log( this, "AddValue 11");                 
1190 #endif                    
1191                     objectPr.PRobjectInfo.AddValue(pr.PRname, var, ref objectPr.PRsi, ref objectPr.PRmemberData);             
1192                 }
1193             }
1194             else
1195                 ParseError(pr, objectPr);
1196         }
1197
1198         // Object member end encountered in stream
1199         [System.Security.SecurityCritical]  // auto-generated
1200         private void ParseMemberEnd(ParseRecord pr)
1201         {
1202             SerTrace.Log( this, "ParseMemberEnd");
1203             switch (pr.PRmemberTypeEnum)
1204             {
1205                 case InternalMemberTypeE.Item:
1206                     ParseArrayMemberEnd(pr);
1207                     return;
1208                 case InternalMemberTypeE.Field:
1209                     if (pr.PRmemberValueEnum == InternalMemberValueE.Nested)
1210                         ParseObjectEnd(pr);
1211                     break;
1212                 default:
1213                     ParseError(pr, (ParseRecord)stack.Peek());
1214                     break;
1215             }
1216         }
1217
1218         // Processes a string object by getting an internal ID for it and registering it with the objectManager
1219         [System.Security.SecurityCritical]  // auto-generated
1220         private void ParseString(ParseRecord pr, ParseRecord parentPr)
1221         {
1222             SerTrace.Log( this, "ParseString Entry ",pr.PRobjectId," ",pr.PRvalue," ",pr.PRisRegistered);
1223             // Process String class
1224             if ((!pr.PRisRegistered) && (pr.PRobjectId > 0))
1225             {
1226                 SerTrace.Log( this, "ParseString  RegisterObject ",pr.PRvalue," ",pr.PRobjectId);                           
1227                 // String is treated as an object if it has an id
1228                 //m_objectManager.RegisterObject(pr.PRvalue, pr.PRobjectId);
1229                 RegisterObject(pr.PRvalue, pr, parentPr, true);
1230             }
1231         }
1232
1233
1234         [System.Security.SecurityCritical]  // auto-generated
1235         private void RegisterObject(Object obj, ParseRecord pr, ParseRecord objectPr)
1236         {
1237             RegisterObject(obj, pr, objectPr, false);
1238         }
1239
1240         [System.Security.SecurityCritical]  // auto-generated
1241         private void RegisterObject(Object obj, ParseRecord pr, ParseRecord objectPr, bool bIsString)
1242         {
1243             if (!pr.PRisRegistered)
1244             {
1245                 pr.PRisRegistered = true;
1246
1247                 SerializationInfo si = null;
1248                 long parentId = 0;
1249                 MemberInfo memberInfo = null;
1250                 int[] indexMap = null;
1251
1252                 if (objectPr != null)
1253                 {
1254                     indexMap = objectPr.PRindexMap;
1255                     parentId = objectPr.PRobjectId;                 
1256
1257                     if (objectPr.PRobjectInfo != null)
1258                     {
1259                         if (!objectPr.PRobjectInfo.isSi)
1260                         {
1261                             // ParentId is only used if there is a memberInfo
1262
1263                             memberInfo = objectPr.PRobjectInfo.GetMemberInfo(pr.PRname);
1264                         }
1265                     }
1266                 }
1267                 // SerializationInfo is always needed for ISerialization                        
1268                 si = pr.PRsi;
1269
1270                 SerTrace.Log( this, "RegisterObject 0bj ",obj," objectId ",pr.PRobjectId," si ", si," parentId ",parentId," memberInfo ",memberInfo, " indexMap "+indexMap);
1271                 if (bIsString)
1272                     m_objectManager.RegisterString((String)obj, pr.PRobjectId, si, parentId, memberInfo); 
1273                 else
1274                     m_objectManager.RegisterObject(obj, pr.PRobjectId, si, parentId, memberInfo, indexMap); 
1275             }
1276         }
1277
1278
1279         // Assigns an internal ID associated with the binary id number
1280
1281         // Older formatters generate ids for valuetypes using a different counter than ref types. Newer ones use
1282         // a single counter, only value types have a negative value. Need a way to handle older formats.
1283         private const int THRESHOLD_FOR_VALUETYPE_IDS = Int32.MaxValue;
1284         private bool bOldFormatDetected = false;
1285         private IntSizedArray   valTypeObjectIdTable;
1286
1287         [System.Security.SecurityCritical]  // auto-generated
1288         internal long GetId(long objectId)
1289         {
1290
1291             if (!bFullDeserialization)
1292                 InitFullDeserialization();
1293
1294
1295             if (objectId > 0)
1296                 return objectId;
1297             
1298             if (bOldFormatDetected || objectId == -1)
1299             {
1300                 // Alarm bells. This is an old format. Deal with it.
1301                 bOldFormatDetected = true;
1302                 if (valTypeObjectIdTable == null)
1303                     valTypeObjectIdTable = new IntSizedArray();
1304
1305                 long tempObjId = 0;
1306                 if ((tempObjId = valTypeObjectIdTable[(int)objectId]) == 0)
1307                 {
1308                     tempObjId = THRESHOLD_FOR_VALUETYPE_IDS + objectId;
1309                     valTypeObjectIdTable[(int)objectId] = (int)tempObjId;
1310                 }
1311                 return tempObjId;
1312             }
1313             return -1 * objectId;
1314         }
1315
1316
1317         // Trace which includes a single dimensional int array
1318         [Conditional("SER_LOGGING")]                        
1319         private void IndexTraceMessage(String message, int[] index)
1320         {
1321             StringBuilder sb = StringBuilderCache.Acquire(10);
1322             sb.Append("[");     
1323             for (int i=0; i<index.Length; i++)
1324             {
1325                 sb.Append(index[i]);
1326                 if (i != index.Length -1)
1327                     sb.Append(",");
1328             }
1329             sb.Append("]");             
1330             SerTrace.Log( this, message," ", StringBuilderCache.GetStringAndRelease(sb));
1331         }
1332
1333         [System.Security.SecurityCritical]  // auto-generated
1334         internal Type Bind(String assemblyString, String typeString)
1335         {
1336             Type type = null;
1337             if (m_binder != null)
1338                 type = m_binder.BindToType(assemblyString, typeString);
1339             if ((object)type == null)
1340                 type= FastBindToType(assemblyString, typeString);
1341
1342             return type;
1343         }
1344
1345         internal class TypeNAssembly
1346         {
1347             public Type type;
1348             public String assemblyName;
1349         }
1350
1351         NameCache typeCache = new NameCache();
1352         [System.Security.SecurityCritical]  // auto-generated
1353         internal Type FastBindToType(String assemblyName, String typeName)
1354         {
1355             Type type = null;
1356
1357             TypeNAssembly entry = (TypeNAssembly)typeCache.GetCachedValue(typeName);
1358
1359             if (entry == null || entry.assemblyName != assemblyName)
1360             {
1361                 Assembly assm = null;
1362                 if (bSimpleAssembly)
1363                 {
1364                     try {
1365                           sfileIOPermission.Assert();
1366                           try {
1367 #if FEATURE_FUSION
1368                               assm = ObjectReader.ResolveSimpleAssemblyName(new AssemblyName(assemblyName));
1369 #else // FEATURE_FUSION
1370                               Assembly.Load(assemblyName);
1371 #endif // FEATURE_FUSION
1372                           }
1373                           finally {
1374                               CodeAccessPermission.RevertAssert();
1375                           }
1376                     }
1377                     catch(Exception e){
1378                         SerTrace.Log( this, "FastBindTypeType ",e.ToString());
1379                     }
1380
1381                     if (assm == null)
1382                         return null;
1383
1384                     ObjectReader.GetSimplyNamedTypeFromAssembly(assm, typeName, ref type);
1385                 }
1386                 else {
1387                     try
1388                     {
1389                           sfileIOPermission.Assert();
1390                           try {
1391                               assm = Assembly.Load(assemblyName);
1392                           }
1393                           finally {
1394                               CodeAccessPermission.RevertAssert();
1395                           }
1396                     }
1397                     catch (Exception e)
1398                     {
1399                         SerTrace.Log( this, "FastBindTypeType ",e.ToString());
1400                     }
1401
1402                     if (assm == null)
1403                         return null;
1404
1405                     type = FormatterServices.GetTypeFromAssembly(assm, typeName);
1406                 }
1407
1408                 if ((object)type == null)
1409                     return null;
1410
1411                 // before adding it to cache, let us do the security check 
1412                 CheckTypeForwardedTo(assm, type.Assembly, type);
1413                
1414                 entry = new TypeNAssembly();
1415                 entry.type = type;
1416                 entry.assemblyName = assemblyName;
1417                 typeCache.SetCachedValue(entry);
1418             }
1419            return entry.type;
1420         }
1421
1422         [System.Security.SecurityCritical]  // auto-generated
1423         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
1424         private static Assembly ResolveSimpleAssemblyName(AssemblyName assemblyName)
1425         {
1426             StackCrawlMark stackMark = StackCrawlMark.LookForMe;
1427             Assembly assm = RuntimeAssembly.LoadWithPartialNameInternal(assemblyName, null, ref stackMark);
1428             if (assm == null && assemblyName != null)
1429                 assm = RuntimeAssembly.LoadWithPartialNameInternal(assemblyName.Name, null, ref stackMark);
1430             return assm;
1431         }
1432
1433         [System.Security.SecurityCritical]  // auto-generated
1434         private static void GetSimplyNamedTypeFromAssembly(Assembly assm, string typeName, ref Type type)
1435         {
1436             // Catching any exceptions that could be thrown from a failure on assembly load
1437             // This is necessary, for example, if there are generic parameters that are qualified with a version of the assembly that predates the one available
1438             try
1439             {
1440                 type = FormatterServices.GetTypeFromAssembly(assm, typeName);
1441             }
1442             catch (TypeLoadException) { }
1443             catch (FileNotFoundException) { }
1444             catch (FileLoadException) { }
1445             catch (BadImageFormatException) { }
1446             
1447             if ((object)type == null)
1448             {
1449                 type = Type.GetType(typeName, ObjectReader.ResolveSimpleAssemblyName, new TopLevelAssemblyTypeResolver(assm).ResolveType, false /* throwOnError */);
1450             }
1451         }
1452
1453
1454         private String previousAssemblyString;
1455         private String previousName;
1456         private Type previousType;
1457         //private int hit;
1458         
1459         [System.Security.SecurityCritical]  // auto-generated
1460         internal Type GetType(BinaryAssemblyInfo assemblyInfo, String name)
1461         {
1462             Type objectType = null;
1463
1464             if (((previousName != null) && (previousName.Length == name.Length) && (previousName.Equals(name))) &&
1465                 ((previousAssemblyString != null) && (previousAssemblyString.Length == assemblyInfo.assemblyString.Length) &&(previousAssemblyString.Equals(assemblyInfo.assemblyString))))
1466             {
1467                 objectType = previousType;
1468                 //Console.WriteLine("Hit "+(++hit)+" "+objectType);
1469             }
1470             else
1471             {
1472                 objectType = Bind(assemblyInfo.assemblyString, name);
1473                 if ((object)objectType == null)
1474                 {
1475                     Assembly sourceAssembly = assemblyInfo.GetAssembly();
1476
1477                     if (bSimpleAssembly)
1478                     {
1479                         ObjectReader.GetSimplyNamedTypeFromAssembly(sourceAssembly, name, ref objectType);
1480                     }
1481                     else
1482                     {
1483                         objectType = FormatterServices.GetTypeFromAssembly(sourceAssembly, name);
1484                     }
1485
1486                     // here let us do the security check 
1487                     if (objectType != null)
1488                     {
1489                         CheckTypeForwardedTo(sourceAssembly, objectType.Assembly, objectType);
1490                     }
1491                 }
1492
1493                 previousAssemblyString = assemblyInfo.assemblyString;
1494                 previousName = name;
1495                 previousType = objectType;
1496             }
1497             //Console.WriteLine("name "+name+" assembly "+assemblyInfo.assemblyString+" objectType "+objectType);
1498             return objectType;
1499         }
1500
1501         [SecuritySafeCritical]
1502         private static void CheckTypeForwardedTo(Assembly sourceAssembly, Assembly destAssembly, Type resolvedType)
1503         {
1504             if ( !FormatterServices.UnsafeTypeForwardersIsEnabled() && sourceAssembly != destAssembly )
1505             {
1506                 // we have a type forward to attribute !
1507
1508                 // we can try to see if the dest assembly has less permissionSet
1509                 if (!destAssembly.PermissionSet.IsSubsetOf(sourceAssembly.PermissionSet))
1510                 {
1511                     // let us try to see if typeforwardedfrom is there
1512
1513                     // let us hit the cache first
1514                     TypeInformation typeInfo = BinaryFormatter.GetTypeInformation(resolvedType);
1515                     if (typeInfo.HasTypeForwardedFrom)
1516                     {
1517                         Assembly typeFowardedFromAssembly = null;
1518                         try
1519                         {
1520                             // if this Assembly.Load failed, we still want to throw security exception
1521                             typeFowardedFromAssembly = Assembly.Load(typeInfo.AssemblyString);
1522                         }
1523                         catch { }
1524
1525                         if (typeFowardedFromAssembly != sourceAssembly)
1526                         {
1527                             // throw security exception
1528                             throw new SecurityException() { Demanded = sourceAssembly.PermissionSet };
1529                         }
1530                     }
1531                     else
1532                     {
1533                         // throw security exception
1534                         throw new SecurityException() { Demanded = sourceAssembly.PermissionSet };
1535                     }
1536                 }
1537             }         
1538         }
1539
1540         internal sealed class TopLevelAssemblyTypeResolver
1541         {
1542             private Assembly m_topLevelAssembly;
1543
1544             public TopLevelAssemblyTypeResolver(Assembly topLevelAssembly)
1545             {
1546                 m_topLevelAssembly = topLevelAssembly;
1547             }
1548
1549             public Type ResolveType(Assembly assembly, string simpleTypeName, bool ignoreCase)
1550             {
1551                 if (assembly == null)
1552                     assembly = m_topLevelAssembly;
1553
1554                 return assembly.GetType(simpleTypeName, false, ignoreCase);
1555             }
1556         }
1557     }
1558 }