SoapObjectReader.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / clr / src / ManagedLibraries / SoapSerializer / SoapObjectReader.cs / 1 / SoapObjectReader.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
//============================================================
// 
// Class: ObjectReader 
//
// Author: Peter de Jong ([....]) 
//
// Purpose: DeSerializes XML in SOAP Format into an an object graph
//
// Date:  June 10, 1999 
//
//=========================================================== 
 
namespace System.Runtime.Serialization.Formatters.Soap {
 
    using System;
    using System.IO;
    using System.Reflection;
    using System.Collections; 
    using System.Text;
    using System.Runtime.Remoting; 
    using System.Runtime.Remoting.Metadata.W3cXsd2001; 
    using System.Runtime.Remoting.Messaging;
    using System.Runtime.Serialization; 
    using System.Security;
    using System.Security.Permissions;
    using System.Diagnostics;
    using System.Globalization; 

    internal sealed class ObjectReader 
    { 

        // System.Serializer information 
        internal ObjectIDGenerator m_idGenerator;
        internal Stream m_stream;
        internal ISurrogateSelector m_surrogates;
        internal StreamingContext m_context; 
        internal ObjectManager m_objectManager;
        internal InternalFE formatterEnums; 
        internal SerializationBinder m_binder; 

        internal SoapHandler soapHandler; //Set from SoapHandler 

        // Fake Top object and headers
        internal long topId = 0;
        internal SerStack topStack; // Stack for placing ProcessRecords if the top record cannot be serialized on the first pass. 
        internal bool isTopObjectSecondPass = false;
        internal bool isTopObjectResolved = true; 
        internal bool isHeaderHandlerCalled = false; 
        internal Exception deserializationSecurityException = null;
        internal Object handlerObject = null; 
        internal Object topObject;
        internal long soapFaultId;
        internal Header[] headers;
        internal Header[] newheaders; 
        internal bool IsFakeTopObject = false;
        internal HeaderHandler handler; 
        internal SerObjectInfoInit serObjectInfoInit = null; 
        internal IFormatterConverter m_formatterConverter = null;
 
        // Stack of Object ParseRecords
        internal SerStack stack = new SerStack("ObjectReader Object Stack");

        // ValueType Fixup Stack 
        internal SerStack valueFixupStack = new SerStack("ValueType Fixup Stack");
 
        // Generate Object Id's 
        internal Hashtable objectIdTable = new Hashtable(25); // holds the keyId value from the XML input and associated internal Id
        internal long objectIds = 0; 

        internal int paramPosition = 0; //Position of parameter if soap top fake record.

        internal int majorVersion = 0; 
        internal int minorVersion = 0;
 
        internal String faultString = null; 

        // GetType - eliminate redundant Type.GetType() 
        //internal Hashtable typeTable = new Hashtable(10);

        internal static SecurityPermission serializationPermission = new SecurityPermission(SecurityPermissionFlag.SerializationFormatter);
        private static FileIOPermission sfileIOPermission = new FileIOPermission(PermissionState.Unrestricted); 

 
        internal ObjectReader(Stream stream, ISurrogateSelector selector, StreamingContext context, InternalFE formatterEnums, SerializationBinder binder) 
        {
            InternalST.Soap( this, "Constructor ISurrogateSelector ",((selector == null)?"null selector ":"selector present")); 

            if (stream==null)
            {
                throw new ArgumentNullException("stream", SoapUtil.GetResourceString("ArgumentNull_Stream")); 
            }
 
            m_stream=stream; 
            m_surrogates = selector;
            m_context = context; 
            m_binder =  binder;
            this.formatterEnums = formatterEnums;

            InternalST.Soap( this, "Constructor formatterEnums.FEtopObject ",formatterEnums.FEtopObject); 
            if (formatterEnums.FEtopObject != null)
                IsFakeTopObject = true; 
            else 
                IsFakeTopObject = false;
 
            m_formatterConverter = new FormatterConverter();
        }

 
        private ObjectManager GetObjectManager() {
            new SecurityPermission(SecurityPermissionFlag.SerializationFormatter).Assert(); 
            return new ObjectManager(m_surrogates, m_context); 
      }
 



        // Deserialize the stream into an object graph. 
        internal Object Deserialize(HeaderHandler handler, ISerParser serParser)
        { 
 
            InternalST.Soap( this, "Deserialize Entry handler", handler);
 
            if (serParser == null)
                throw new ArgumentNullException("serParser", String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("ArgumentNull_WithParamName"), serParser));

 
            deserializationSecurityException = null;
            try { 
                serializationPermission.Demand(); 
            } catch(Exception e ) {
                deserializationSecurityException = e; 
            }
            catch {
                deserializationSecurityException = new Exception(SoapUtil.GetResourceString("Serialization_NonClsCompliantException"));
            } 

            this.handler = handler; 
            isTopObjectSecondPass = false; 
            isHeaderHandlerCalled = false;
 
            if (handler != null)
                IsFakeTopObject = true;

            m_idGenerator = new ObjectIDGenerator(); 

 
            m_objectManager = GetObjectManager(); 

            serObjectInfoInit = new SerObjectInfoInit(); 
            objectIdTable.Clear();
            objectIds = 0;

            // Will call back to ParseObject, ParseHeader for each object found 
            serParser.Run();
 
            if (handler != null) 
            {
                InternalST.Soap( this, "Deserialize Fixup Before Delegate Invoke"); 
                m_objectManager.DoFixups(); // Fixup for headers

                // Header handler isn't invoked until method name is known from body fake record
                // Except for SoapFault, in which case it is invoked below 
                if (handlerObject == null)
                { 
                    InternalST.Soap( this, "Deserialize Before SoapFault Delegate Invoke "); 
                    handlerObject = handler(newheaders);
                    InternalST.Soap( this, "Deserialize after SoapFault Delegate Invoke"); 
                }


                // SoapFault creation Create a fake Pr for the handlerObject to use. 
                // Create a member for the fake pr with name __fault;
                if ((soapFaultId > 0) && (handlerObject != null)) 
                { 
                    InternalST.Soap( this, "Deserialize SoapFault ");
                    topStack = new SerStack("Top ParseRecords"); 
                    ParseRecord pr = new ParseRecord();
                    pr.PRparseTypeEnum = InternalParseTypeE.Object;
                    pr.PRobjectPositionEnum = InternalObjectPositionE.Top;
                    pr.PRparseStateEnum = InternalParseStateE.Object; 
                    pr.PRname = "Response";
                    topStack.Push(pr); 
                    pr = new ParseRecord(); 
                    pr.PRparseTypeEnum = InternalParseTypeE.Member;
                    pr.PRobjectPositionEnum = InternalObjectPositionE.Child; 
                    pr.PRmemberTypeEnum = InternalMemberTypeE.Field;
                    pr.PRmemberValueEnum = InternalMemberValueE.Reference;
                    pr.PRparseStateEnum = InternalParseStateE.Member;
                    pr.PRname = "__fault"; 
                    pr.PRidRef = soapFaultId;
                    topStack.Push(pr); 
                    pr = new ParseRecord(); 
                    pr.PRparseTypeEnum = InternalParseTypeE.ObjectEnd;
                    pr.PRobjectPositionEnum = InternalObjectPositionE.Top; 
                    pr.PRparseStateEnum = InternalParseStateE.Object;
                    pr.PRname = "Response";
                    topStack.Push(pr);
                    isTopObjectResolved = false; 
                }
            } 
 

            // Resolve fake top object if necessary 
            if (!isTopObjectResolved)
            {
                //resolve top object
                InternalST.Soap( this, "Deserialize TopObject Second Pass"); 
                isTopObjectSecondPass = true;
                topStack.Reverse(); 
                // The top of the stack now contains the fake record 
                // When it is Parsed, the handler object will be substituted
                // for it in ParseObject. 
                int topStackLength = topStack.Count();
                ParseRecord pr = null;
                for (int i=0; i 0))
                            {
                                pr.PRobjectInfo = CreateReadObjectInfo(pr.PRdtType, fi.FieldNames, fi.FieldTypes, pr.PRassemblyName);
                            } 
                        }
                    } 
                    else 
                    {
                        // Handler object has not yet been asked for the real object 
                        // Stack the parse record until the second pass
                        isTopObjectResolved = false;
                        topStack = new SerStack("Top ParseRecords");
                        InternalST.Soap( this, "ParseObject Handler Push "+pr.PRname); 
                        topStack.Push(pr.Copy());
                        return; 
                    } 
                }
                else if (formatterEnums.FEtopObject != null) 
                {
                    // SoapMessage will be used as the real object
                    InternalST.Soap( this, "ParseObject FakeTopObject with SoapMessage ");
                    if (isTopObjectSecondPass) 
                    {
                        // This creates a the SoapMessage object as the real object, at this point it is an unitialized object. 
                        pr.PRnewObj = new InternalSoapMessage(); 
                        pr.PRdtType = typeof(InternalSoapMessage);
                        CheckSecurity(pr); 
                        if (formatterEnums.FEtopObject != null)
                        {
                            ISoapMessage soapMessage = (ISoapMessage)formatterEnums.FEtopObject;
                            pr.PRobjectInfo = CreateReadObjectInfo(pr.PRdtType, soapMessage.ParamNames, soapMessage.ParamTypes, pr.PRassemblyName); 
                        }
                    } 
                    else 
                    {
                        // Stack the parse record until the second pass 
                        isTopObjectResolved = false;
                        topStack = new SerStack("Top ParseRecords");
                        topStack.Push(pr.Copy());
                        return; 
                    }
                } 
            } 
            else if (pr.PRdtType == Converter.typeofString)
            { 
                // String as a top level object
                if (pr.PRvalue != null)
                {
                    pr.PRnewObj = pr.PRvalue; 
                    if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
                    { 
                        InternalST.Soap( this, "ParseObject String as top level, Top Object Resolved"); 
                        isTopObjectResolved = true;
                        topObject = pr.PRnewObj; 
                        //stack.Pop();
                        return;
                    }
                    else 
                    {
                        InternalST.Soap( this, "ParseObject  String as an object"); 
                        stack.Pop(); 
                        RegisterObject(pr.PRnewObj, pr, (ParseRecord)stack.Peek());
                        return; 
                    }
                }
                else
                { 
                    // xml Doesn't have the value until later
                    return; 
                } 
            }
            else 
            {
                if (pr.PRdtType == null)
                {
                    ParseRecord objectPr = (ParseRecord)stack.Peek(); 
                    if (objectPr.PRdtType == Converter.typeofSoapFault)
                    { 
                        InternalST.Soap( this, "ParseObject unknown SoapFault detail"); 
                        throw new ServerException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_SoapFault"),faultString));
                    } 

                    throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_TypeElement"),pr.PRname));
                }
                CheckSerializable(pr.PRdtType); 
                if (IsRemoting && formatterEnums.FEsecurityLevel != TypeFilterLevel.Full)
                    pr.PRnewObj = FormatterServices.GetSafeUninitializedObject(pr.PRdtType); 
                else 
                    pr.PRnewObj = FormatterServices.GetUninitializedObject(pr.PRdtType);
 
                CheckSecurity(pr);
                // Run the OnDeserializing methods
                m_objectManager.RaiseOnDeserializingEvent(pr.PRnewObj);
 
            }
 
            if (pr.PRnewObj == null) 
                throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_TopObjectInstantiate"),pr.PRdtType));
 
            long genId = pr.PRobjectId;
            if (genId < 1)
                pr.PRobjectId = GetId("GenId-"+objectIds);
 

            if (IsFakeTopObject && pr.PRobjectPositionEnum == InternalObjectPositionE.Top) 
            { 
                InternalST.Soap( this, "ParseObject fake Top object resolved ",pr.PRnewObj);
                isTopObjectResolved = true; 
                topObject = pr.PRnewObj;
            }

            if (pr.PRobjectInfo == null) 
                pr.PRobjectInfo = CreateReadObjectInfo(pr.PRdtType, pr.PRassemblyName);
            pr.PRobjectInfo.obj = pr.PRnewObj; 
 
            if (IsFakeTopObject && pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
            { 
                InternalST.Soap( this, "ParseObject AddValue to fake object ",pr.PRobjectInfo.obj);
                // Add the methodName to top object, either InternalSoapMessage or object returned by handler
                pr.PRobjectInfo.AddValue("__methodName", pr.PRname);
                pr.PRobjectInfo.AddValue("__keyToNamespaceTable", soapHandler.keyToNamespaceTable); 
                pr.PRobjectInfo.AddValue("__paramNameList", pr.PRobjectInfo.SetFakeObject());
                if (formatterEnums.FEtopObject != null) 
                    pr.PRobjectInfo.AddValue("__xmlNameSpace", pr.PRxmlNameSpace); 
            }
 
            InternalST.Soap( this, "ParseObject Exit ");
        }

 
        private bool IsWhiteSpace(String value)
        { 
            for (int i=0; i111
                    objectPr.PRnewObj = Converter.FromString(objectPr.PRvalue, Converter.ToCode(objectPr.PRdtType)); 
                    CheckSecurity(objectPr);
                    isTopObjectResolved = true; 
                    topObject = objectPr.PRnewObj; 
                    return;
 
                }
                else if ((!isTopObjectResolved) && (objectPr.PRdtType != Converter.typeofSoapFault))
                {
                    InternalST.Soap( this, "ParseObjectEnd Top but not String"); 
                    // Need to keep top record on object stack until finished building top stack
                    topStack.Push(pr.Copy()); 
                    // Note this is PRparseRecordId and not objectId 
                    if (objectPr.PRparseRecordId == pr.PRparseRecordId)
                    { 
                        // This handles the case of top stack containing nested objects and
                        // referenced objects. If nested objects the objects are not placed
                        // on stack, only topstack. If referenced objects they are placed on
                        // stack and need to be popped. 
                        stack.Pop();
                    } 
                    return; 
                }
            } 

            stack.Pop();

            ParseRecord parentPr = (ParseRecord)stack.Peek(); 

            if (objectPr.PRobjectTypeEnum == InternalObjectTypeE.Array) 
            { 
                if (objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top)
                { 
                    InternalST.Soap( this, "ParseObjectEnd  Top Object (Array) Resolved");
                    isTopObjectResolved = true;
                    topObject = objectPr.PRnewObj;
                } 

                InternalST.Soap( this, "ParseArray  RegisterObject ",objectPr.PRobjectId," ",objectPr.PRnewObj.GetType()); 
                RegisterObject(objectPr.PRnewObj, objectPr, parentPr); 

                return; 
            }

            if (objectPr.PRobjectInfo != null)
            { 
                objectPr.PRobjectInfo.PopulateObjectMembers();
            } 
 
            if (objectPr.PRnewObj == null)
            { 
                if (objectPr.PRdtType == Converter.typeofString)
                {
                    InternalST.Soap( this, "ParseObjectEnd String ");
                    if (objectPr.PRvalue == null) 
                        objectPr.PRvalue = String.Empty; // Not a null object, but an empty string
                    objectPr.PRnewObj = objectPr.PRvalue; 
                    CheckSecurity(objectPr); 
                }
                else 
                    throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_ObjectMissing"),pr.PRname));
            }

            // Registration is after object is populated 
            if (!objectPr.PRisRegistered && objectPr.PRobjectId > 0)
            { 
                InternalST.Soap( this, "ParseObjectEnd Register Object ",objectPr.PRobjectId," ",objectPr.PRnewObj.GetType()); 
                RegisterObject(objectPr.PRnewObj, objectPr, parentPr);
            } 

            if (objectPr.PRisValueTypeFixup)
            {
                InternalST.Soap( this, "ParseObjectEnd  ValueTypeFixup ",objectPr.PRnewObj.GetType()); 
                ValueFixup fixup = (ValueFixup)valueFixupStack.Pop(); //Value fixup
                fixup.Fixup(objectPr, parentPr);  // Value fixup 
            } 

            if (objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top) 
            {
                InternalST.Soap( this, "ParseObjectEnd  Top Object Resolved ",objectPr.PRnewObj.GetType());
                isTopObjectResolved = true;
                topObject = objectPr.PRnewObj; 
            }
 
            if (objectPr.PRnewObj is SoapFault) 
                soapFaultId = objectPr.PRobjectId;
 
            if (objectPr.PRobjectInfo != null)
            {
                if (objectPr.PRobjectInfo.bfake && !objectPr.PRobjectInfo.bSoapFault)
                    objectPr.PRobjectInfo.AddValue("__fault", null); // need this because SerializationObjectInfo throws an exception if a name being referenced is missing 

                objectPr.PRobjectInfo.ObjectEnd(); 
            } 

            InternalST.Soap( this, "ParseObjectEnd  Exit ",objectPr.PRnewObj," id: ",objectPr.PRobjectId); 
        }


 
        // Array object encountered in stream
        private void ParseArray(ParseRecord pr) 
        { 
            InternalST.Soap( this, "ParseArray Entry");
            pr.Dump(); 

            long genId = pr.PRobjectId;
            if (genId < 1)
                pr.PRobjectId = GetId("GenId-"+objectIds); 

            if ((pr.PRarrayElementType != null) && (pr.PRarrayElementType.IsEnum)) 
                pr.PRisEnum = true; 

            if (pr.PRarrayTypeEnum == InternalArrayTypeE.Base64) 
            {
                if (pr.PRvalue == null)
                {
                    pr.PRnewObj = new Byte[0]; 
                    CheckSecurity(pr);
                } 
                else 
                {
                    // Used for arrays of Base64 and also for a parameter of Base64 
                    InternalST.Soap( this, "ParseArray bin.base64 ",pr.PRvalue.Length," ",pr.PRvalue);

                    if (pr.PRdtType == Converter.typeofSoapBase64Binary)
                    { 
                        // Parameter - Case where the return type is a SoapENC:base64 but the parameter type is xsd:base64Binary
                        pr.PRnewObj = SoapBase64Binary.Parse(pr.PRvalue); 
                        CheckSecurity(pr); 
                    }
                    else 
                    {
                        // ByteArray
                        if (pr.PRvalue.Length > 0)
                        { 
                            pr.PRnewObj = Convert.FromBase64String(FilterBin64(pr.PRvalue));
                            CheckSecurity(pr); 
                        } 
                        else
                        { 
                            pr.PRnewObj = new Byte[0];
                            CheckSecurity(pr);
                        }
                    } 
                }
 
                if (stack.Peek() == pr) 
                {
                    InternalST.Soap( this, "ParseArray, bin.base64 has been stacked"); 
                    stack.Pop();
                }
                if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
                { 
                    InternalST.Soap( this, "ParseArray, bin.base64 Top Object");
                    topObject = pr.PRnewObj; 
                    isTopObjectResolved = true; 
                }
 
                ParseRecord parentPr = (ParseRecord)stack.Peek();

                // Base64 can be registered at this point because it is populated
                InternalST.Soap( this, "ParseArray  RegisterObject ",pr.PRobjectId," ",pr.PRnewObj.GetType()); 
                RegisterObject(pr.PRnewObj, pr, parentPr);
 
            } 
            else if ((pr.PRnewObj != null) && Converter.IsWriteAsByteArray(pr.PRarrayElementTypeCode))
            { 
                // Primtive typed Array has already been read
                if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
                {
                    topObject = pr.PRnewObj; 
                    isTopObjectResolved = true;
                } 
 
                ParseRecord parentPr = (ParseRecord)stack.Peek();
 
                // Primitive typed array can be registered at this point because it is populated
                InternalST.Soap( this, "ParseArray  RegisterObject ",pr.PRobjectId," ",pr.PRnewObj.GetType());
                RegisterObject(pr.PRnewObj, pr, parentPr);
            } 
            else if ((pr.PRarrayTypeEnum == InternalArrayTypeE.Jagged) || (pr.PRarrayTypeEnum == InternalArrayTypeE.Single))
            { 
                // Multidimensional jagged array or single array 
                InternalST.Soap( this, "ParseArray Before Jagged,Simple create ",pr.PRarrayElementType," ",(pr.PRrank >0?pr.PRlengthA[0].ToString():"0"));
                if ((pr.PRlowerBoundA == null) || (pr.PRlowerBoundA[0] == 0)) 
                {
                    pr.PRnewObj = Array.CreateInstance(pr.PRarrayElementType, (pr.PRrank>0?pr.PRlengthA[0]:0));
                    pr.PRisLowerBound = false;
                } 
                else
                { 
                    pr.PRnewObj = Array.CreateInstance(pr.PRarrayElementType, pr.PRlengthA, pr.PRlowerBoundA); 
                    pr.PRisLowerBound = true;
                } 

                if (pr.PRarrayTypeEnum == InternalArrayTypeE.Single)
                {
                    if (!pr.PRisLowerBound && (Converter.IsWriteAsByteArray(pr.PRarrayElementTypeCode))) 
                    {
                        pr.PRprimitiveArray = new PrimitiveArray(pr.PRarrayElementTypeCode, (Array)pr.PRnewObj); 
                    } 
                    else if (!pr.PRarrayElementType.IsValueType && pr.PRlowerBoundA== null)
                    { 
                        pr.PRobjectA = (Object[])pr.PRnewObj;
                    }
                }
                CheckSecurity(pr); 

                InternalST.Soap( this, "ParseArray Jagged,Simple Array ",pr.PRnewObj.GetType()); 
 
                // For binary, headers comes in as an array of header objects
                if (pr.PRobjectPositionEnum == InternalObjectPositionE.Headers) 
                {
                    InternalST.Soap( this, "ParseArray header array");
                    headers = (Header[])pr.PRnewObj;
                } 

                pr.PRindexMap = new int[1]; 
 

            } 
            else if (pr.PRarrayTypeEnum == InternalArrayTypeE.Rectangular)
            {
                // Rectangle array
 
                pr.PRisLowerBound = false;
                if (pr.PRlowerBoundA != null) 
                { 
                    for (int i=0; i-1; irank--) 
            {
                // Find the current or lower dimension which can be incremented. 
                if (pr.PRrectangularMap[irank] < pr.PRlengthA[irank]-1)
                {
                    // The current dimension is at maximum. Increase the next lower dimension by 1
                    pr.PRrectangularMap[irank]++; 
                    if (irank < pr.PRrank-1)
                    { 
                        // The current dimension and higher dimensions are zeroed. 
                        for (int i = irank+1; i 0)
                        NextRectangleMap(objectPr); // Rectangle array, calculate position in array 
 
                    for (int i=0; i 0))
                            { 
                                if (pr.PRvalue == null) 
                                    pr.PRvalue = ""; //can't register null value, this must be a string so set to empty string.
 
                                InternalST.Soap( this, "ParseMember RegisterObject ",pr.PRvalue," ",pr.PRobjectId);
                                RegisterObject(pr.PRvalue, pr, objectPr);
                            }
 
                            // Object Class with no memberInfo data
                            // < 
                            if (pr.PRdtType == Converter.typeofSystemVoid) 
                            {
                                InternalST.Soap( this, "AddValue 9"); 
                                objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRdtType);
                            }
                            else if (objectPr.PRobjectInfo.isSi)
                            { 
                                // ISerializable are added as strings, the conversion to type is done by the
                                // ISerializable object 
                                InternalST.Soap( this, "AddValue 10"); 
                                objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRvalue);
                            } 
                        }
                    }
                }
                else 
                {
                    Object var = null; 
                    if (pr.PRvarValue != null) 
                        var = pr.PRvarValue;
                    else 
                        var = Converter.FromString(pr.PRvalue, pr.PRdtTypeCode);
                    // Not a string, convert the value
                    InternalST.Soap( this, "ParseMember Converting primitive and storing");
                    stack.Dump(); 
                    InternalST.Soap( this, "ParseMember pr "+pr.Trace());
                    InternalST.Soap( this, "ParseMember objectPr ",objectPr.Trace()); 
 
                    InternalST.Soap( this, "AddValue 11");
                    if (pr.PRdtTypeCode == InternalPrimitiveTypeE.QName && var != null) 
                    {
                        SoapQName soapQName = (SoapQName)var;
                        if (soapQName.Key != null)
                        { 
                            if (soapQName.Key.Length == 0)
                                soapQName.Namespace = (String)soapHandler.keyToNamespaceTable["xmlns"]; 
                            else 
                                soapQName.Namespace = (String)soapHandler.keyToNamespaceTable["xmlns"+":"+soapQName.Key];
                        } 
                    }
                    objectPr.PRobjectInfo.AddValue(pr.PRname, var);
                }
            } 
            else
                ParseError(pr, objectPr); 
        } 

        // Object member end encountered in stream 
        private void ParseMemberEnd(ParseRecord pr)
        {
            InternalST.Soap( this, "ParseMemberEnd");
            switch(pr.PRmemberTypeEnum) 
            {
                case InternalMemberTypeE.Item: 
                    ParseArrayMemberEnd(pr); 
                    return;
                case InternalMemberTypeE.Field: 
                    if (pr.PRmemberValueEnum == InternalMemberValueE.Nested)
                        ParseObjectEnd(pr);
                    break;
                default: 
                    if (pr.PRmemberValueEnum == InternalMemberValueE.Nested)
                        ParseObjectEnd(pr); 
                    else 
                        ParseError(pr, (ParseRecord)stack.Peek());
                    break; 
            }
        }

        // Processes a string object by getting an internal ID for it and registering it with the objectManager 
        private void ParseString(ParseRecord pr, ParseRecord parentPr)
        { 
            InternalST.Soap( this, "ParseString Entry ",pr.PRobjectId," ",pr.PRvalue," ",pr.PRisRegistered); 

            // If there is a string and it wasn't marked as a null object, then it is an empty string 
            if (pr.PRvalue == null)
                pr.PRvalue = "";

            // Process String class 
            if  ((!pr.PRisRegistered) && (pr.PRobjectId > 0))
            { 
                InternalST.Soap( this, "ParseString  RegisterObject ",pr.PRvalue," ",pr.PRobjectId); 
                // String is treated as an object if it has an id
                //m_objectManager.RegisterObject(pr.PRvalue, pr.PRobjectId); 
                RegisterObject(pr.PRvalue, pr, parentPr);
            }
        }
 

        private void RegisterObject(Object obj, ParseRecord pr, ParseRecord objectPr) 
        { 
            if (!pr.PRisRegistered)
            { 
                pr.PRisRegistered = true;

                SerializationInfo si = null;
                long parentId = 0; 
                MemberInfo memberInfo = null;
                int[] indexMap = null; 
 
                if (objectPr != null)
                { 
                    indexMap = objectPr.PRindexMap;
                    parentId = objectPr.PRobjectId;

                    if (objectPr.PRobjectInfo != null) 
                    {
                        if (!objectPr.PRobjectInfo.isSi) 
                        { 
                            // ParentId is only used if there is a memberInfo
                            InternalST.Soap( this, "RegisterObject GetMemberInfo parent ",objectPr.PRobjectInfo.objectType," name looking for ", pr.PRname," field obj "+obj); 
                            memberInfo = objectPr.PRobjectInfo.GetMemberInfo(pr.PRname);
                        }
                    }
                } 
                if (pr.PRobjectInfo != null)
                { 
                    // SerializationInfo is always needed for ISerialization 
                    si = pr.PRobjectInfo.si;
                } 

                InternalST.Soap( this, "RegisterObject 0bj ",obj," objectId ",pr.PRobjectId," si ", si," parentId ",parentId," memberInfo ",memberInfo, " indexMap "+indexMap);
                m_objectManager.RegisterObject(obj, pr.PRobjectId, si, parentId, memberInfo, indexMap);
            } 
        }
 
 
        internal void SetVersion(int major, int minor)
        { 
            // Don't do version checking if property is set to Simple
            if (formatterEnums.FEassemblyFormat != FormatterAssemblyStyle.Simple)
            {
                this.majorVersion = major; 
                this.minorVersion = minor;
            } 
        } 

 
        // Assigns an internal ID associated with the xml id attribute

        String inKeyId = null;
        long outKeyId = 0; 
        internal long GetId(String keyId)
        { 
            if (keyId == null) 
                throw new ArgumentNullException("keyId", String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("ArgumentNull_WithParamName"), "keyId"));
 
            if (keyId != inKeyId)
            {
                inKeyId = keyId;
                String idString = null; 
                InternalST.Soap( this, "GetId Entry ",keyId);
                if (keyId[0] == '#') 
                    idString = keyId.Substring(1); 
                else
                    idString = keyId; 

                Object idObj = objectIdTable[idString];
                if (idObj == null)
                { 
                    outKeyId = ++objectIds;
                    objectIdTable[idString] = outKeyId; 
                    InternalST.Soap( this, "GetId Exit new ID ",outKeyId); 
                }
                else 
                {
                    InternalST.Soap( this, "GetId Exit oldId ",(Int64)idObj);
                    outKeyId =  (Int64)idObj;
                } 
            }
            InternalST.Soap( this, "GetId  in id ",keyId, " out id ", outKeyId); 
            return outKeyId; 
        }
 
        // Trace which includes a single dimensional int array
        [Conditional("SER_LOGGING")]
        private void IndexTraceMessage(String message, int[] index)
        { 
            StringBuilder sb = new StringBuilder(10);
            sb.Append("["); 
            for (int i=0; i
// Author: Peter de Jong ([....]) 
//
// Purpose: DeSerializes XML in SOAP Format into an an object graph
//
// Date:  June 10, 1999 
//
//=========================================================== 
 
namespace System.Runtime.Serialization.Formatters.Soap {
 
    using System;
    using System.IO;
    using System.Reflection;
    using System.Collections; 
    using System.Text;
    using System.Runtime.Remoting; 
    using System.Runtime.Remoting.Metadata.W3cXsd2001; 
    using System.Runtime.Remoting.Messaging;
    using System.Runtime.Serialization; 
    using System.Security;
    using System.Security.Permissions;
    using System.Diagnostics;
    using System.Globalization; 

    internal sealed class ObjectReader 
    { 

        // System.Serializer information 
        internal ObjectIDGenerator m_idGenerator;
        internal Stream m_stream;
        internal ISurrogateSelector m_surrogates;
        internal StreamingContext m_context; 
        internal ObjectManager m_objectManager;
        internal InternalFE formatterEnums; 
        internal SerializationBinder m_binder; 

        internal SoapHandler soapHandler; //Set from SoapHandler 

        // Fake Top object and headers
        internal long topId = 0;
        internal SerStack topStack; // Stack for placing ProcessRecords if the top record cannot be serialized on the first pass. 
        internal bool isTopObjectSecondPass = false;
        internal bool isTopObjectResolved = true; 
        internal bool isHeaderHandlerCalled = false; 
        internal Exception deserializationSecurityException = null;
        internal Object handlerObject = null; 
        internal Object topObject;
        internal long soapFaultId;
        internal Header[] headers;
        internal Header[] newheaders; 
        internal bool IsFakeTopObject = false;
        internal HeaderHandler handler; 
        internal SerObjectInfoInit serObjectInfoInit = null; 
        internal IFormatterConverter m_formatterConverter = null;
 
        // Stack of Object ParseRecords
        internal SerStack stack = new SerStack("ObjectReader Object Stack");

        // ValueType Fixup Stack 
        internal SerStack valueFixupStack = new SerStack("ValueType Fixup Stack");
 
        // Generate Object Id's 
        internal Hashtable objectIdTable = new Hashtable(25); // holds the keyId value from the XML input and associated internal Id
        internal long objectIds = 0; 

        internal int paramPosition = 0; //Position of parameter if soap top fake record.

        internal int majorVersion = 0; 
        internal int minorVersion = 0;
 
        internal String faultString = null; 

        // GetType - eliminate redundant Type.GetType() 
        //internal Hashtable typeTable = new Hashtable(10);

        internal static SecurityPermission serializationPermission = new SecurityPermission(SecurityPermissionFlag.SerializationFormatter);
        private static FileIOPermission sfileIOPermission = new FileIOPermission(PermissionState.Unrestricted); 

 
        internal ObjectReader(Stream stream, ISurrogateSelector selector, StreamingContext context, InternalFE formatterEnums, SerializationBinder binder) 
        {
            InternalST.Soap( this, "Constructor ISurrogateSelector ",((selector == null)?"null selector ":"selector present")); 

            if (stream==null)
            {
                throw new ArgumentNullException("stream", SoapUtil.GetResourceString("ArgumentNull_Stream")); 
            }
 
            m_stream=stream; 
            m_surrogates = selector;
            m_context = context; 
            m_binder =  binder;
            this.formatterEnums = formatterEnums;

            InternalST.Soap( this, "Constructor formatterEnums.FEtopObject ",formatterEnums.FEtopObject); 
            if (formatterEnums.FEtopObject != null)
                IsFakeTopObject = true; 
            else 
                IsFakeTopObject = false;
 
            m_formatterConverter = new FormatterConverter();
        }

 
        private ObjectManager GetObjectManager() {
            new SecurityPermission(SecurityPermissionFlag.SerializationFormatter).Assert(); 
            return new ObjectManager(m_surrogates, m_context); 
      }
 



        // Deserialize the stream into an object graph. 
        internal Object Deserialize(HeaderHandler handler, ISerParser serParser)
        { 
 
            InternalST.Soap( this, "Deserialize Entry handler", handler);
 
            if (serParser == null)
                throw new ArgumentNullException("serParser", String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("ArgumentNull_WithParamName"), serParser));

 
            deserializationSecurityException = null;
            try { 
                serializationPermission.Demand(); 
            } catch(Exception e ) {
                deserializationSecurityException = e; 
            }
            catch {
                deserializationSecurityException = new Exception(SoapUtil.GetResourceString("Serialization_NonClsCompliantException"));
            } 

            this.handler = handler; 
            isTopObjectSecondPass = false; 
            isHeaderHandlerCalled = false;
 
            if (handler != null)
                IsFakeTopObject = true;

            m_idGenerator = new ObjectIDGenerator(); 

 
            m_objectManager = GetObjectManager(); 

            serObjectInfoInit = new SerObjectInfoInit(); 
            objectIdTable.Clear();
            objectIds = 0;

            // Will call back to ParseObject, ParseHeader for each object found 
            serParser.Run();
 
            if (handler != null) 
            {
                InternalST.Soap( this, "Deserialize Fixup Before Delegate Invoke"); 
                m_objectManager.DoFixups(); // Fixup for headers

                // Header handler isn't invoked until method name is known from body fake record
                // Except for SoapFault, in which case it is invoked below 
                if (handlerObject == null)
                { 
                    InternalST.Soap( this, "Deserialize Before SoapFault Delegate Invoke "); 
                    handlerObject = handler(newheaders);
                    InternalST.Soap( this, "Deserialize after SoapFault Delegate Invoke"); 
                }


                // SoapFault creation Create a fake Pr for the handlerObject to use. 
                // Create a member for the fake pr with name __fault;
                if ((soapFaultId > 0) && (handlerObject != null)) 
                { 
                    InternalST.Soap( this, "Deserialize SoapFault ");
                    topStack = new SerStack("Top ParseRecords"); 
                    ParseRecord pr = new ParseRecord();
                    pr.PRparseTypeEnum = InternalParseTypeE.Object;
                    pr.PRobjectPositionEnum = InternalObjectPositionE.Top;
                    pr.PRparseStateEnum = InternalParseStateE.Object; 
                    pr.PRname = "Response";
                    topStack.Push(pr); 
                    pr = new ParseRecord(); 
                    pr.PRparseTypeEnum = InternalParseTypeE.Member;
                    pr.PRobjectPositionEnum = InternalObjectPositionE.Child; 
                    pr.PRmemberTypeEnum = InternalMemberTypeE.Field;
                    pr.PRmemberValueEnum = InternalMemberValueE.Reference;
                    pr.PRparseStateEnum = InternalParseStateE.Member;
                    pr.PRname = "__fault"; 
                    pr.PRidRef = soapFaultId;
                    topStack.Push(pr); 
                    pr = new ParseRecord(); 
                    pr.PRparseTypeEnum = InternalParseTypeE.ObjectEnd;
                    pr.PRobjectPositionEnum = InternalObjectPositionE.Top; 
                    pr.PRparseStateEnum = InternalParseStateE.Object;
                    pr.PRname = "Response";
                    topStack.Push(pr);
                    isTopObjectResolved = false; 
                }
            } 
 

            // Resolve fake top object if necessary 
            if (!isTopObjectResolved)
            {
                //resolve top object
                InternalST.Soap( this, "Deserialize TopObject Second Pass"); 
                isTopObjectSecondPass = true;
                topStack.Reverse(); 
                // The top of the stack now contains the fake record 
                // When it is Parsed, the handler object will be substituted
                // for it in ParseObject. 
                int topStackLength = topStack.Count();
                ParseRecord pr = null;
                for (int i=0; i 0))
                            {
                                pr.PRobjectInfo = CreateReadObjectInfo(pr.PRdtType, fi.FieldNames, fi.FieldTypes, pr.PRassemblyName);
                            } 
                        }
                    } 
                    else 
                    {
                        // Handler object has not yet been asked for the real object 
                        // Stack the parse record until the second pass
                        isTopObjectResolved = false;
                        topStack = new SerStack("Top ParseRecords");
                        InternalST.Soap( this, "ParseObject Handler Push "+pr.PRname); 
                        topStack.Push(pr.Copy());
                        return; 
                    } 
                }
                else if (formatterEnums.FEtopObject != null) 
                {
                    // SoapMessage will be used as the real object
                    InternalST.Soap( this, "ParseObject FakeTopObject with SoapMessage ");
                    if (isTopObjectSecondPass) 
                    {
                        // This creates a the SoapMessage object as the real object, at this point it is an unitialized object. 
                        pr.PRnewObj = new InternalSoapMessage(); 
                        pr.PRdtType = typeof(InternalSoapMessage);
                        CheckSecurity(pr); 
                        if (formatterEnums.FEtopObject != null)
                        {
                            ISoapMessage soapMessage = (ISoapMessage)formatterEnums.FEtopObject;
                            pr.PRobjectInfo = CreateReadObjectInfo(pr.PRdtType, soapMessage.ParamNames, soapMessage.ParamTypes, pr.PRassemblyName); 
                        }
                    } 
                    else 
                    {
                        // Stack the parse record until the second pass 
                        isTopObjectResolved = false;
                        topStack = new SerStack("Top ParseRecords");
                        topStack.Push(pr.Copy());
                        return; 
                    }
                } 
            } 
            else if (pr.PRdtType == Converter.typeofString)
            { 
                // String as a top level object
                if (pr.PRvalue != null)
                {
                    pr.PRnewObj = pr.PRvalue; 
                    if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
                    { 
                        InternalST.Soap( this, "ParseObject String as top level, Top Object Resolved"); 
                        isTopObjectResolved = true;
                        topObject = pr.PRnewObj; 
                        //stack.Pop();
                        return;
                    }
                    else 
                    {
                        InternalST.Soap( this, "ParseObject  String as an object"); 
                        stack.Pop(); 
                        RegisterObject(pr.PRnewObj, pr, (ParseRecord)stack.Peek());
                        return; 
                    }
                }
                else
                { 
                    // xml Doesn't have the value until later
                    return; 
                } 
            }
            else 
            {
                if (pr.PRdtType == null)
                {
                    ParseRecord objectPr = (ParseRecord)stack.Peek(); 
                    if (objectPr.PRdtType == Converter.typeofSoapFault)
                    { 
                        InternalST.Soap( this, "ParseObject unknown SoapFault detail"); 
                        throw new ServerException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_SoapFault"),faultString));
                    } 

                    throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_TypeElement"),pr.PRname));
                }
                CheckSerializable(pr.PRdtType); 
                if (IsRemoting && formatterEnums.FEsecurityLevel != TypeFilterLevel.Full)
                    pr.PRnewObj = FormatterServices.GetSafeUninitializedObject(pr.PRdtType); 
                else 
                    pr.PRnewObj = FormatterServices.GetUninitializedObject(pr.PRdtType);
 
                CheckSecurity(pr);
                // Run the OnDeserializing methods
                m_objectManager.RaiseOnDeserializingEvent(pr.PRnewObj);
 
            }
 
            if (pr.PRnewObj == null) 
                throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_TopObjectInstantiate"),pr.PRdtType));
 
            long genId = pr.PRobjectId;
            if (genId < 1)
                pr.PRobjectId = GetId("GenId-"+objectIds);
 

            if (IsFakeTopObject && pr.PRobjectPositionEnum == InternalObjectPositionE.Top) 
            { 
                InternalST.Soap( this, "ParseObject fake Top object resolved ",pr.PRnewObj);
                isTopObjectResolved = true; 
                topObject = pr.PRnewObj;
            }

            if (pr.PRobjectInfo == null) 
                pr.PRobjectInfo = CreateReadObjectInfo(pr.PRdtType, pr.PRassemblyName);
            pr.PRobjectInfo.obj = pr.PRnewObj; 
 
            if (IsFakeTopObject && pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
            { 
                InternalST.Soap( this, "ParseObject AddValue to fake object ",pr.PRobjectInfo.obj);
                // Add the methodName to top object, either InternalSoapMessage or object returned by handler
                pr.PRobjectInfo.AddValue("__methodName", pr.PRname);
                pr.PRobjectInfo.AddValue("__keyToNamespaceTable", soapHandler.keyToNamespaceTable); 
                pr.PRobjectInfo.AddValue("__paramNameList", pr.PRobjectInfo.SetFakeObject());
                if (formatterEnums.FEtopObject != null) 
                    pr.PRobjectInfo.AddValue("__xmlNameSpace", pr.PRxmlNameSpace); 
            }
 
            InternalST.Soap( this, "ParseObject Exit ");
        }

 
        private bool IsWhiteSpace(String value)
        { 
            for (int i=0; i111
                    objectPr.PRnewObj = Converter.FromString(objectPr.PRvalue, Converter.ToCode(objectPr.PRdtType)); 
                    CheckSecurity(objectPr);
                    isTopObjectResolved = true; 
                    topObject = objectPr.PRnewObj; 
                    return;
 
                }
                else if ((!isTopObjectResolved) && (objectPr.PRdtType != Converter.typeofSoapFault))
                {
                    InternalST.Soap( this, "ParseObjectEnd Top but not String"); 
                    // Need to keep top record on object stack until finished building top stack
                    topStack.Push(pr.Copy()); 
                    // Note this is PRparseRecordId and not objectId 
                    if (objectPr.PRparseRecordId == pr.PRparseRecordId)
                    { 
                        // This handles the case of top stack containing nested objects and
                        // referenced objects. If nested objects the objects are not placed
                        // on stack, only topstack. If referenced objects they are placed on
                        // stack and need to be popped. 
                        stack.Pop();
                    } 
                    return; 
                }
            } 

            stack.Pop();

            ParseRecord parentPr = (ParseRecord)stack.Peek(); 

            if (objectPr.PRobjectTypeEnum == InternalObjectTypeE.Array) 
            { 
                if (objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top)
                { 
                    InternalST.Soap( this, "ParseObjectEnd  Top Object (Array) Resolved");
                    isTopObjectResolved = true;
                    topObject = objectPr.PRnewObj;
                } 

                InternalST.Soap( this, "ParseArray  RegisterObject ",objectPr.PRobjectId," ",objectPr.PRnewObj.GetType()); 
                RegisterObject(objectPr.PRnewObj, objectPr, parentPr); 

                return; 
            }

            if (objectPr.PRobjectInfo != null)
            { 
                objectPr.PRobjectInfo.PopulateObjectMembers();
            } 
 
            if (objectPr.PRnewObj == null)
            { 
                if (objectPr.PRdtType == Converter.typeofString)
                {
                    InternalST.Soap( this, "ParseObjectEnd String ");
                    if (objectPr.PRvalue == null) 
                        objectPr.PRvalue = String.Empty; // Not a null object, but an empty string
                    objectPr.PRnewObj = objectPr.PRvalue; 
                    CheckSecurity(objectPr); 
                }
                else 
                    throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_ObjectMissing"),pr.PRname));
            }

            // Registration is after object is populated 
            if (!objectPr.PRisRegistered && objectPr.PRobjectId > 0)
            { 
                InternalST.Soap( this, "ParseObjectEnd Register Object ",objectPr.PRobjectId," ",objectPr.PRnewObj.GetType()); 
                RegisterObject(objectPr.PRnewObj, objectPr, parentPr);
            } 

            if (objectPr.PRisValueTypeFixup)
            {
                InternalST.Soap( this, "ParseObjectEnd  ValueTypeFixup ",objectPr.PRnewObj.GetType()); 
                ValueFixup fixup = (ValueFixup)valueFixupStack.Pop(); //Value fixup
                fixup.Fixup(objectPr, parentPr);  // Value fixup 
            } 

            if (objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top) 
            {
                InternalST.Soap( this, "ParseObjectEnd  Top Object Resolved ",objectPr.PRnewObj.GetType());
                isTopObjectResolved = true;
                topObject = objectPr.PRnewObj; 
            }
 
            if (objectPr.PRnewObj is SoapFault) 
                soapFaultId = objectPr.PRobjectId;
 
            if (objectPr.PRobjectInfo != null)
            {
                if (objectPr.PRobjectInfo.bfake && !objectPr.PRobjectInfo.bSoapFault)
                    objectPr.PRobjectInfo.AddValue("__fault", null); // need this because SerializationObjectInfo throws an exception if a name being referenced is missing 

                objectPr.PRobjectInfo.ObjectEnd(); 
            } 

            InternalST.Soap( this, "ParseObjectEnd  Exit ",objectPr.PRnewObj," id: ",objectPr.PRobjectId); 
        }


 
        // Array object encountered in stream
        private void ParseArray(ParseRecord pr) 
        { 
            InternalST.Soap( this, "ParseArray Entry");
            pr.Dump(); 

            long genId = pr.PRobjectId;
            if (genId < 1)
                pr.PRobjectId = GetId("GenId-"+objectIds); 

            if ((pr.PRarrayElementType != null) && (pr.PRarrayElementType.IsEnum)) 
                pr.PRisEnum = true; 

            if (pr.PRarrayTypeEnum == InternalArrayTypeE.Base64) 
            {
                if (pr.PRvalue == null)
                {
                    pr.PRnewObj = new Byte[0]; 
                    CheckSecurity(pr);
                } 
                else 
                {
                    // Used for arrays of Base64 and also for a parameter of Base64 
                    InternalST.Soap( this, "ParseArray bin.base64 ",pr.PRvalue.Length," ",pr.PRvalue);

                    if (pr.PRdtType == Converter.typeofSoapBase64Binary)
                    { 
                        // Parameter - Case where the return type is a SoapENC:base64 but the parameter type is xsd:base64Binary
                        pr.PRnewObj = SoapBase64Binary.Parse(pr.PRvalue); 
                        CheckSecurity(pr); 
                    }
                    else 
                    {
                        // ByteArray
                        if (pr.PRvalue.Length > 0)
                        { 
                            pr.PRnewObj = Convert.FromBase64String(FilterBin64(pr.PRvalue));
                            CheckSecurity(pr); 
                        } 
                        else
                        { 
                            pr.PRnewObj = new Byte[0];
                            CheckSecurity(pr);
                        }
                    } 
                }
 
                if (stack.Peek() == pr) 
                {
                    InternalST.Soap( this, "ParseArray, bin.base64 has been stacked"); 
                    stack.Pop();
                }
                if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
                { 
                    InternalST.Soap( this, "ParseArray, bin.base64 Top Object");
                    topObject = pr.PRnewObj; 
                    isTopObjectResolved = true; 
                }
 
                ParseRecord parentPr = (ParseRecord)stack.Peek();

                // Base64 can be registered at this point because it is populated
                InternalST.Soap( this, "ParseArray  RegisterObject ",pr.PRobjectId," ",pr.PRnewObj.GetType()); 
                RegisterObject(pr.PRnewObj, pr, parentPr);
 
            } 
            else if ((pr.PRnewObj != null) && Converter.IsWriteAsByteArray(pr.PRarrayElementTypeCode))
            { 
                // Primtive typed Array has already been read
                if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
                {
                    topObject = pr.PRnewObj; 
                    isTopObjectResolved = true;
                } 
 
                ParseRecord parentPr = (ParseRecord)stack.Peek();
 
                // Primitive typed array can be registered at this point because it is populated
                InternalST.Soap( this, "ParseArray  RegisterObject ",pr.PRobjectId," ",pr.PRnewObj.GetType());
                RegisterObject(pr.PRnewObj, pr, parentPr);
            } 
            else if ((pr.PRarrayTypeEnum == InternalArrayTypeE.Jagged) || (pr.PRarrayTypeEnum == InternalArrayTypeE.Single))
            { 
                // Multidimensional jagged array or single array 
                InternalST.Soap( this, "ParseArray Before Jagged,Simple create ",pr.PRarrayElementType," ",(pr.PRrank >0?pr.PRlengthA[0].ToString():"0"));
                if ((pr.PRlowerBoundA == null) || (pr.PRlowerBoundA[0] == 0)) 
                {
                    pr.PRnewObj = Array.CreateInstance(pr.PRarrayElementType, (pr.PRrank>0?pr.PRlengthA[0]:0));
                    pr.PRisLowerBound = false;
                } 
                else
                { 
                    pr.PRnewObj = Array.CreateInstance(pr.PRarrayElementType, pr.PRlengthA, pr.PRlowerBoundA); 
                    pr.PRisLowerBound = true;
                } 

                if (pr.PRarrayTypeEnum == InternalArrayTypeE.Single)
                {
                    if (!pr.PRisLowerBound && (Converter.IsWriteAsByteArray(pr.PRarrayElementTypeCode))) 
                    {
                        pr.PRprimitiveArray = new PrimitiveArray(pr.PRarrayElementTypeCode, (Array)pr.PRnewObj); 
                    } 
                    else if (!pr.PRarrayElementType.IsValueType && pr.PRlowerBoundA== null)
                    { 
                        pr.PRobjectA = (Object[])pr.PRnewObj;
                    }
                }
                CheckSecurity(pr); 

                InternalST.Soap( this, "ParseArray Jagged,Simple Array ",pr.PRnewObj.GetType()); 
 
                // For binary, headers comes in as an array of header objects
                if (pr.PRobjectPositionEnum == InternalObjectPositionE.Headers) 
                {
                    InternalST.Soap( this, "ParseArray header array");
                    headers = (Header[])pr.PRnewObj;
                } 

                pr.PRindexMap = new int[1]; 
 

            } 
            else if (pr.PRarrayTypeEnum == InternalArrayTypeE.Rectangular)
            {
                // Rectangle array
 
                pr.PRisLowerBound = false;
                if (pr.PRlowerBoundA != null) 
                { 
                    for (int i=0; i-1; irank--) 
            {
                // Find the current or lower dimension which can be incremented. 
                if (pr.PRrectangularMap[irank] < pr.PRlengthA[irank]-1)
                {
                    // The current dimension is at maximum. Increase the next lower dimension by 1
                    pr.PRrectangularMap[irank]++; 
                    if (irank < pr.PRrank-1)
                    { 
                        // The current dimension and higher dimensions are zeroed. 
                        for (int i = irank+1; i 0)
                        NextRectangleMap(objectPr); // Rectangle array, calculate position in array 
 
                    for (int i=0; i 0))
                            { 
                                if (pr.PRvalue == null) 
                                    pr.PRvalue = ""; //can't register null value, this must be a string so set to empty string.
 
                                InternalST.Soap( this, "ParseMember RegisterObject ",pr.PRvalue," ",pr.PRobjectId);
                                RegisterObject(pr.PRvalue, pr, objectPr);
                            }
 
                            // Object Class with no memberInfo data
                            // < 
                            if (pr.PRdtType == Converter.typeofSystemVoid) 
                            {
                                InternalST.Soap( this, "AddValue 9"); 
                                objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRdtType);
                            }
                            else if (objectPr.PRobjectInfo.isSi)
                            { 
                                // ISerializable are added as strings, the conversion to type is done by the
                                // ISerializable object 
                                InternalST.Soap( this, "AddValue 10"); 
                                objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRvalue);
                            } 
                        }
                    }
                }
                else 
                {
                    Object var = null; 
                    if (pr.PRvarValue != null) 
                        var = pr.PRvarValue;
                    else 
                        var = Converter.FromString(pr.PRvalue, pr.PRdtTypeCode);
                    // Not a string, convert the value
                    InternalST.Soap( this, "ParseMember Converting primitive and storing");
                    stack.Dump(); 
                    InternalST.Soap( this, "ParseMember pr "+pr.Trace());
                    InternalST.Soap( this, "ParseMember objectPr ",objectPr.Trace()); 
 
                    InternalST.Soap( this, "AddValue 11");
                    if (pr.PRdtTypeCode == InternalPrimitiveTypeE.QName && var != null) 
                    {
                        SoapQName soapQName = (SoapQName)var;
                        if (soapQName.Key != null)
                        { 
                            if (soapQName.Key.Length == 0)
                                soapQName.Namespace = (String)soapHandler.keyToNamespaceTable["xmlns"]; 
                            else 
                                soapQName.Namespace = (String)soapHandler.keyToNamespaceTable["xmlns"+":"+soapQName.Key];
                        } 
                    }
                    objectPr.PRobjectInfo.AddValue(pr.PRname, var);
                }
            } 
            else
                ParseError(pr, objectPr); 
        } 

        // Object member end encountered in stream 
        private void ParseMemberEnd(ParseRecord pr)
        {
            InternalST.Soap( this, "ParseMemberEnd");
            switch(pr.PRmemberTypeEnum) 
            {
                case InternalMemberTypeE.Item: 
                    ParseArrayMemberEnd(pr); 
                    return;
                case InternalMemberTypeE.Field: 
                    if (pr.PRmemberValueEnum == InternalMemberValueE.Nested)
                        ParseObjectEnd(pr);
                    break;
                default: 
                    if (pr.PRmemberValueEnum == InternalMemberValueE.Nested)
                        ParseObjectEnd(pr); 
                    else 
                        ParseError(pr, (ParseRecord)stack.Peek());
                    break; 
            }
        }

        // Processes a string object by getting an internal ID for it and registering it with the objectManager 
        private void ParseString(ParseRecord pr, ParseRecord parentPr)
        { 
            InternalST.Soap( this, "ParseString Entry ",pr.PRobjectId," ",pr.PRvalue," ",pr.PRisRegistered); 

            // If there is a string and it wasn't marked as a null object, then it is an empty string 
            if (pr.PRvalue == null)
                pr.PRvalue = "";

            // Process String class 
            if  ((!pr.PRisRegistered) && (pr.PRobjectId > 0))
            { 
                InternalST.Soap( this, "ParseString  RegisterObject ",pr.PRvalue," ",pr.PRobjectId); 
                // String is treated as an object if it has an id
                //m_objectManager.RegisterObject(pr.PRvalue, pr.PRobjectId); 
                RegisterObject(pr.PRvalue, pr, parentPr);
            }
        }
 

        private void RegisterObject(Object obj, ParseRecord pr, ParseRecord objectPr) 
        { 
            if (!pr.PRisRegistered)
            { 
                pr.PRisRegistered = true;

                SerializationInfo si = null;
                long parentId = 0; 
                MemberInfo memberInfo = null;
                int[] indexMap = null; 
 
                if (objectPr != null)
                { 
                    indexMap = objectPr.PRindexMap;
                    parentId = objectPr.PRobjectId;

                    if (objectPr.PRobjectInfo != null) 
                    {
                        if (!objectPr.PRobjectInfo.isSi) 
                        { 
                            // ParentId is only used if there is a memberInfo
                            InternalST.Soap( this, "RegisterObject GetMemberInfo parent ",objectPr.PRobjectInfo.objectType," name looking for ", pr.PRname," field obj "+obj); 
                            memberInfo = objectPr.PRobjectInfo.GetMemberInfo(pr.PRname);
                        }
                    }
                } 
                if (pr.PRobjectInfo != null)
                { 
                    // SerializationInfo is always needed for ISerialization 
                    si = pr.PRobjectInfo.si;
                } 

                InternalST.Soap( this, "RegisterObject 0bj ",obj," objectId ",pr.PRobjectId," si ", si," parentId ",parentId," memberInfo ",memberInfo, " indexMap "+indexMap);
                m_objectManager.RegisterObject(obj, pr.PRobjectId, si, parentId, memberInfo, indexMap);
            } 
        }
 
 
        internal void SetVersion(int major, int minor)
        { 
            // Don't do version checking if property is set to Simple
            if (formatterEnums.FEassemblyFormat != FormatterAssemblyStyle.Simple)
            {
                this.majorVersion = major; 
                this.minorVersion = minor;
            } 
        } 

 
        // Assigns an internal ID associated with the xml id attribute

        String inKeyId = null;
        long outKeyId = 0; 
        internal long GetId(String keyId)
        { 
            if (keyId == null) 
                throw new ArgumentNullException("keyId", String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("ArgumentNull_WithParamName"), "keyId"));
 
            if (keyId != inKeyId)
            {
                inKeyId = keyId;
                String idString = null; 
                InternalST.Soap( this, "GetId Entry ",keyId);
                if (keyId[0] == '#') 
                    idString = keyId.Substring(1); 
                else
                    idString = keyId; 

                Object idObj = objectIdTable[idString];
                if (idObj == null)
                { 
                    outKeyId = ++objectIds;
                    objectIdTable[idString] = outKeyId; 
                    InternalST.Soap( this, "GetId Exit new ID ",outKeyId); 
                }
                else 
                {
                    InternalST.Soap( this, "GetId Exit oldId ",(Int64)idObj);
                    outKeyId =  (Int64)idObj;
                } 
            }
            InternalST.Soap( this, "GetId  in id ",keyId, " out id ", outKeyId); 
            return outKeyId; 
        }
 
        // Trace which includes a single dimensional int array
        [Conditional("SER_LOGGING")]
        private void IndexTraceMessage(String message, int[] index)
        { 
            StringBuilder sb = new StringBuilder(10);
            sb.Append("["); 
            for (int i=0; i

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK