ApplicationProxyInternal.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / MS / Internal / AppModel / ApplicationProxyInternal.cs / 7 / ApplicationProxyInternal.cs

                            //------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: This is an internal proxy wrapper class over Application class. 
//              This derives from MarshalByRefObject and thus facilitates calling 
//              the AppCode from DocobjHost that may be running in a different
//              AppDomain.  The other thing it allows is to be able to create 
//              the App Object on the right thread by exposing a delegate that
//              could be set to point to the code that creates the AppObject and
//              invoking the delegate from the right thread.
// 
// History:
//  07/03/2003 [....]  Created 
//  10/04/2005 [....] Documented & refactored class; primary reason was ensure 
//                      disposal of all XpsViewer (DocumentApplication)
//                      resources 
//-----------------------------------------------------------------------------

//**
//** IMPORTANT: Running arbitrary application code in the context of an incoming call from the browser 
//**    should be avoided. This could lead to unexpected reentrancy (on either side) or making the
//      browser frame unresponsive while the application code is running. Bug 1139336 illustrates 
//      what can happen if the application code enters a local message loop while the browser is 
//      blocked. To avoid such situations in general, use Dispatcher.BeginInvoke() instead of making
//      direct calls into unknown code. 


using System;
using System.Diagnostics; 
using System.IO;
using System.IO.Packaging; 
using System.Reflection; 
using System.Runtime.InteropServices;
using System.Runtime.Serialization; 
using System.Runtime.Serialization.Formatters.Binary;
using System.Security;
using System.Security.Permissions;
using System.Threading; 
using System.Windows;
using System.Windows.Controls; 
using System.Windows.Controls.Primitives; 
using System.Windows.Input;
using System.Windows.Interop; 
using System.Windows.Navigation;
using System.Windows.Threading;

using MS.Internal; 
using MS.Internal.Documents;
using MS.Internal.Documents.Application; 
using MS.Internal.IO.Packaging; 
using MS.Internal.IO.Packaging.CompoundFile;
using MS.Internal.PresentationFramework; 
using MS.Internal.Utility;
using MS.Internal.AppModel;
using MS.Utility;
 
//In order to avoid generating warnings about unknown message numbers and
//unknown pragmas when compiling your C# source code with the actual C# compiler, 
//you need to disable warnings 1634 and 1691. (Presharp Documentation) 
#pragma warning disable 1634, 1691
 
namespace MS.Internal.AppModel
{
    // All security sensitive classes should be sealed or protected with InheritanceDemand
    internal sealed class ApplicationProxyInternal : MarshalByRefObject 
    {
        [Serializable] 
        internal class InitData 
        {
            internal IServiceProvider ServiceProvider; 
            internal SecurityCriticalDataForSet MimeType;
            internal SecurityCriticalDataForSet ActivationUri;
            internal string Fragment;
            internal object UcomLoadIStream; 
            internal bool HandleHistoryLoad;
            internal string UserAgentString; 
            internal Rect WindowRect; 
            internal bool ShowWindow;
        }; 

        //-----------------------------------------------------
        //
        //  Constructors 
        //
        //----------------------------------------------------- 
        #region Constructors 

        ///  
        /// ApplicationProxyInternal is created only for browser-hosted applications.
        /// 
        /// 
        /// Critical: 
        ///     1) We want to track creation of ApplicationProxyInternal because it can be used to
        ///        make calls between AppDomains (it's MarshalByRefObject). 
        ///     2) It sets BrowserInteropHelper.IsBrowserHosted, which is critical for set. 
        /// 
        [SecurityCritical] 
        internal ApplicationProxyInternal()
        {
            if (EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose))
            { 
                EventTrace.EventProvider.TraceEvent(EventTrace.Level.verbose, EventTrace.GuidFromId(EventTraceGuidId.HOSTINGGUID), (byte)EventTrace.HostingEvent.AppProxyCtor);
            } 
 
            if (_proxyInstance != null)
            { 
                throw new InvalidOperationException(SR.Get(SRID.MultiSingleton, this.GetType().FullName));
            }
            // Set this here so it will be true for documents or applications (i.e. anything in the browser.)
            BrowserInteropHelper.SetBrowserHosted(true); 
            _proxyInstance = this;
        } 
 
        #endregion Constructors
 
        //------------------------------------------------------
        //
        //  Internal Methods
        // 
        //-----------------------------------------------------
        #region Internal Methods 
 
        public override object InitializeLifetimeService()
        { 
            //Keeps it alive until the AppDomain is teared down which is what we want.
            //Otherwise the .Net remoting infrastructure releases all remote objects in 5 mins
            //if there are no sponsors registered with the lease manager for the remote object.
            //This is an alternative to the client side registering a sponsor by the server object 
            //marking itself to be kept alive for the life of the AppDomain.
            return null; 
        } 

        //Creates the internal RootBrowserWindow. If the startup Uri points 
        //to a Window/NavigationWindow, we still need to create this empty
        //RootBrowserWindow so we can repaint properly inside the browser window

        /// 
        ///  Critical as this code invokes a delegate that accesses critical data.
        ///  TreatAsSafe - creating the browser window for your content to be hosted in is considered safe. 
        ///                       this is considered safe - as you can only control the internal window of the browser. 
        ///                       you cannot change styles of the actual browser window ( verified this).
        ///                       Dangerous behaviors ( e.g. ShowInTaskbar = false) don't work when in browser hosted. 
        ///
        ///
        [SecurityCritical, SecurityTreatAsSafe ]
        internal void CreateRootBrowserWindow() 
        {
            if (_rbw.Value == null) 
            { 

                Application.Current.Dispatcher.Invoke( 
                                    DispatcherPriority.Send,
                                    new DispatcherOperationCallback(_CreateRootBrowserWindowCallback),
                                    null);
            } 
        }
 
        internal bool FocusedElementWantsBackspace() 
        {
            TextBoxBase textBoxBase = Keyboard.FocusedElement as TextBoxBase; 
            if (textBoxBase != null)
            {
                return true; // textBoxBase.IsEmpty
            } 

            PasswordBox passwordBox = Keyboard.FocusedElement as PasswordBox; 
            if (passwordBox != null) 
            {
                return true; // passwordBox.IsEmpty 
            }

            return false;
        } 

        /// 
        ///  Critical as this code calls the critical RootBrowserWindow.CreateAndInitialize() 
        ///
        [SecurityCritical] 
        private object _CreateRootBrowserWindowCallback(object unused)
        {
            if (EventTrace.IsEnabled(EventTrace.Flags.performance))
            { 
                EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.HOSTINGGUID), (byte)EventTrace.HostingEvent.RootBrowserWindowSetupStart);
            } 
 
            RootBrowserWindow = RootBrowserWindow.CreateAndInitialize();
 
            if (EventTrace.IsEnabled(EventTrace.Flags.performance))
            {
                EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.HOSTINGGUID), (byte)EventTrace.HostingEvent.RootBrowserWindowSetupEnd);
            } 
            return null ;
        } 
 
        // Calls the Run method on the app object.
        /// 
        /// Critical - creates a critical delegate, provides the path to LoadFromContainer, which
        ///            is critical, and also calls InitContainer which is critical.  Accesses
        ///            several critical data values (_path, _container, _storageRoot).
        ///          - also sets Uri and _mimeType, which are critical. 
        ///
        [SecurityCritical] 
        internal int Run(InitData initData) 
        {
            if (EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose)) 
            {
                EventTrace.EventProvider.TraceEvent(EventTrace.Level.verbose, EventTrace.GuidFromId(EventTraceGuidId.HOSTINGGUID), (byte)EventTrace.HostingEvent.AppProxyRunStart);
            }
 
            ServiceProvider = initData.ServiceProvider;
            MimeType mimeType = initData.MimeType.Value; 
            _mimeType.Value = mimeType; 
            Uri = initData.ActivationUri.Value;
            WpfWebRequestHelper.DefaultUserAgent = initData.UserAgentString; 

            // These methods are asynchronous.
            Move(initData.WindowRect);
            Show(initData.ShowWindow); 

            switch (mimeType) 
            { 
                case MimeType.Markup:
                case MimeType.Application: 
                    //This is a browser app, the application object has already been created
                    Application.Current.MimeType = mimeType;
                    break;
 
                case MimeType.Document:
                    try 
                    { 
                        InitContainer();
                        PackageDocument document = _document.Value as PackageDocument; 
                        // This will fail to load if the document is not set to a valid PackageDocument.
                        if (document != null)
                        {
                            ContainerActivationHelper.LoadFromContainer( 
                                Uri,
#if CF_Envelope_Activation_Enabled 
                                _storageRoot.Value, 
#endif
                                document.Package, 
                                _serviceProvider);

                            // Set the Application.MimeType
                            // Since loading containers causes the application to be constructed now, 
                            // the initial setting of the MimeType does not get passed to the application.
                            Application.Current.MimeType = mimeType; 
                        } 
                    }
                    catch (Exception e) 
                    {
                        // If we catch an exception while initializing the document, we need
                        // to wrap it in a CrossDomainSerializableException to avoid SecurityExceptions
                        // when the exception is serialized across AppDomains. 
                        throw new CrossDomainSerializableException(e);
                    } 
                    break; 
                case MimeType.Unknown:
                default: 
                    throw new InvalidOperationException();
            }

            Application.Current.Dispatcher.Invoke( 
                DispatcherPriority.Send,
                new DispatcherOperationCallback(_RunDelegate), 
                initData); 

            int exitCode = Application.Current.RunInternal(null); 

            if (EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose))
            {
                EventTrace.EventProvider.TraceEvent(EventTrace.Level.verbose, EventTrace.GuidFromId(EventTraceGuidId.HOSTINGGUID), (byte)EventTrace.HostingEvent.AppProxyRunEnd); 
            }
 
            return exitCode; 
        }
 

        ///
        ///     Critical as this calls a critical function ( LoadHistoryStream).
        /// 
        [SecurityCritical]
        private object _RunDelegate( object args ) 
        { 
            InitData initData = (InitData)args;
 
            Application currentApp = Application.Current;
            if (currentApp != null && !(currentApp is XappLauncherApp))
            {
                // StartupUri is set for XamlViewer so that it can get any URL #fragment 
                // (which is appended below).
                if(_mimeType.Value == MimeType.Markup) 
                { 
                    Debug.Assert(currentApp.StartupUri == null);
                    currentApp.StartupUri = BrowserInteropHelper.Source; 
                }

                string fragment = initData.Fragment;
                if (!String.IsNullOrEmpty(fragment) && currentApp.StartupUri != null) 
                {
                    // Apply Fragment to Application StartupUri. 
                    UriBuilder uriBuilder; 
                    Uri absUri = currentApp.StartupUri;
 
                    if (currentApp.StartupUri.IsAbsoluteUri == false)
                    {
                        absUri = new Uri(BindUriHelper.BaseUri, currentApp.StartupUri);
                    } 

                    uriBuilder = new UriBuilder(absUri); 
                    if (fragment.StartsWith(FRAGMENT_MARKER, StringComparison.Ordinal)) 
                    {
                        fragment = fragment.Substring(FRAGMENT_MARKER.Length); 
                    }
                    uriBuilder.Fragment = fragment;
                    currentApp.StartupUri = uriBuilder.Uri;
                } 

                CreateRootBrowserWindow(); 
            } 

            //If we were started through IPersistHistory::Load, load from the history stream instead 
            //of navigating to the StartupPage
            if (initData.UcomLoadIStream != null && initData.HandleHistoryLoad)
            {
                LoadHistoryStream(DocObjHost.ExtractComStream(initData.UcomLoadIStream), /*firstHistoryLoad=s*/true); 
            }
            return null; 
        } 

        // Show or hide view. 
        internal void Show(bool show)
        {
            _show = show;
            if (Application.Current != null && RootBrowserWindow != null) 
            {
                Application.Current.Dispatcher.BeginInvoke( 
                                    DispatcherPriority.Send, 
                                    new DispatcherOperationCallback(_ShowDelegate),
                                    null); 
            }

        }
 
        private object _ShowDelegate(object ignore)
        { 
            // The RBW might be torn down just before the DispatcherOperation is invoked. 
            if (RootBrowserWindow == null || Application.IsShuttingDown)
                return null; 

            if (_show)
            {
                // The window is shown asynchronously (using Visibility, not Show()) to allow first restoring 
                // the Journal on history navigation. This prevents bug 1367999.
                _rbw.Value.Visibility = Visibility.Visible; 
 
                // initial focus should be on us, not the browser frame
                // Focusing is done asynchronously because Visibility actually changes asynchronously. 
                Application.Current.Dispatcher.BeginInvoke(
                    // same priority as used in the Window.Visibility PropertyChangedCallback
                    DispatcherPriority.Normal,
                    new DispatcherOperationCallback(_FocusDelegate), null); 
            }
            else 
            { 
                _rbw.Value.Visibility = Visibility.Hidden;
            } 

            return null;
        }
 
        /// 
        /// Critical: Calls the critical UnsafeNativeMethods.SetFocus(), which returns a handle to 
        ///     the previously focused window. 
        /// Safe: The handle is not disclosed, and focusing the application's own window (RBW) is okay.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private object _FocusDelegate(object unused)
        {
            if (_rbw.Value != null) 
            {
                try 
                { 
                    MS.Win32.UnsafeNativeMethods.SetFocus(new HandleRef(_rbw.Value, _rbw.Value.CriticalHandle));
                } 
#pragma warning disable 6502
                // The browser may temporarily disable the RBW. Then SetFocus() fails.
                // This is known to happen when the browser pops up the modal dialog about the Information Bar.
                catch (System.ComponentModel.Win32Exception) 
                {
                    Debug.WriteLine("SetFocus() on RootBrowserWindow failed."); 
                } 
#pragma warning restore 6502
            } 
            return null;
        }

        internal void Move(Rect windowRect) 
        {
            if (Application.Current != null && RootBrowserWindow != null) 
            { 
                Application.Current.Dispatcher.BeginInvoke(
                                    DispatcherPriority.Send, 
                                    new DispatcherOperationCallback(_MoveDelegate),
                                    windowRect);
            }
            else 
            {
                // We got UIActivated too early.  Remember the data passed in. 
                _windowRect = windowRect; 
                _rectset = true;
            } 
        }

        private object _MoveDelegate( object moveArgs )
        { 
            // The RBW might be closed just before _MoveDelegate() is called. => check _rbw again.
            if (_rbw.Value != null && !Application.IsShuttingDown) 
            { 
                Rect r = (Rect)moveArgs;
 
                // ResizeMove is implemented by RBW and should be called here
                // since it resizes and moves the WS_CHILD window.  Do not call
                // Height/Width & Top/Left here since they govern the browser
                // window properties. 
                _rbw.Value.ResizeMove((int)r.X, (int)r.Y, (int)r.Width, (int)r.Height);
            } 
            return null; 
        }
 
        // Shutdown the App.
        // Note: The "post" in the method name is legacy. Now all of Application's shutdown work is complete
        // when this method returns. In particular, the managed Dispatcher is shut down.
        /// 
        ///  Critical: Calls Application.CriticalShutdown().
        /// 
        [SecurityCritical] 
        internal void PostShutdown()
        { 
            Cleanup();
            _proxyInstance = null;

            Application app = Application.Current; 
            if (app != null)
            { 
                XappLauncherApp launcherApp = app as XappLauncherApp; 
                if (launcherApp != null)
                { 
                    launcherApp.AbortActivation();
                    Debug.Assert(Application.IsShuttingDown);
                }
                else 
                {
                    //this calls into the internal helper and is hardcoded for a clean 
                    // shutdown 
                    app.CriticalShutdown(0);
 
                    // The Application.Exit event is raised in a Dispatcher callback at Normal priority.
                    // Blocking on this callback here ensures that the event will be raised before we've
                    // disconnected from the browser. An XBAP may want, in particular, to write a cookie.
                    app.Dispatcher.Invoke(DispatcherPriority.Normal, 
                        new DispatcherOperationCallback(delegate(object unused) { return null; }), null);
                } 
            } 
        }
 
        //
        // Activate or Deactivate RootBrowserWindow
        //
 
        internal void Activate(bool fActivate)
        { 
            if (Application.Current != null && RootBrowserWindow != null) 
            {
                Application.Current.Dispatcher.BeginInvoke( 
                                    DispatcherPriority.Send,
                                    new DispatcherOperationCallback(_ActivateDelegate),
                                    fActivate);
            } 
        }
 
        private object _ActivateDelegate(object arg ) 
        {
            if (RootBrowserWindow != null) 
            {
                bool fActivate = (bool)arg;

                _rbw.Value.HandleActivate(fActivate); 
                if (fActivate)
                { 
                    _FocusDelegate(null); 
                }
            } 
            return null;
        }

        internal bool CanInvokeJournalEntry(int entryId) 
        {
            if (Application.Current == null) 
            { 
                return false;
            } 

            return (bool)Application.Current.Dispatcher.Invoke(
            DispatcherPriority.Send,
                (DispatcherOperationCallback) delegate(object unused) 
            {
                NavigationWindow window = Application.Current.MainWindow as NavigationWindow; 
 
                if (window == null)
                    return false; 

                return window.JournalNavigationScope.CanInvokeJournalEntry(entryId);
            },
            null); 
        }
 
        // Private class just to facilitate passing of data back to GetSaveHistoryBytes. 
        private class SaveHistoryReturnInfo
        { 
            internal string uri;
            internal string title;
            internal int entryId;
            internal byte[] saveByteArray ; 
        }
 
        ///  Called by the browser to serialize the entire journal or just the index of 
        /// the current entry. The second case is when an internal Journal update needs to be
        /// reflected in the TravelLog. 
        /// 
        ///  true is the entire Journal is to serialized 
        ///
        ///     Critical as this method accesses critical data. 
        ///              and we elevate for serialization permission.
        /// 
        [SecurityCritical] 
        private object _GetSaveHistoryBytesDelegate(object arg)
        { 
            bool entireJournal = (bool)arg;

            SaveHistoryReturnInfo info = new SaveHistoryReturnInfo();
 
            // When we are here, the browser has just started to shut down, so we should only check
            // whether the application object is shutting down. 
            if (Application.IsApplicationObjectShuttingDown == true) 
                return null;
 
            Invariant.Assert(_rbw.Value != null, "BrowserJournalingError: _rbw should not be null");

            Journal journal = _rbw.Value.Journal;
            Invariant.Assert(journal != null, "BrowserJournalingError: Could not get internal journal for the window"); 

            JournalEntry entry; 
            if (entireJournal) // The application is about to be shut down... 
            {
                NavigationService topNavSvc = _rbw.Value.NavigationService; 
                try
                {
                    topNavSvc.RequestCustomContentStateOnAppShutdown();
                } 
                catch(Exception e)
                { 
                    if(CriticalExceptions.IsCriticalException(e)) 
                    {
                        throw; 
                    }
                }

                journal.PruneKeepAliveEntries(); 

                // Since the current page is not added to the journal until it is replaced, 
                // we add it here explicitly to the internal Journal before serializing it. 
                entry = topNavSvc.MakeJournalEntry(JournalReason.NewContentNavigation);
                if (entry != null && !entry.IsAlive()) 
                {
                    if (entry.JEGroupState.JournalDataStreams != null)
                    {
                        entry.JEGroupState.JournalDataStreams.PrepareForSerialization(); 
                    }
                    journal.UpdateCurrentEntry(entry); 
                } 
                else // Maybe the current content is null or a PageFunction doesn't want to be journaled.
                {   // Then the previous navigable page, if any, should be remembered as current. 
                    entry = journal.GetGoBackEntry();
                    // i. _LoadHistoryStreamDelegate() has a similar special case.
                }
            } 
            else
            {   // (Brittle) Assumption: GetSaveHistoryBytes() is called after the current entry has 
                // been updated in the internal journal but before the new navigation is committed. 
                // This means journal.CurrentEntry is what was just added (or updated).
                // Note that it would be wrong to call topNavSvc.MakeJournalEntry() in this case because 
                // the navigation that just took place may be in a different NavigationService (in a
                // frame), and here we don't know which one it is.
                entry = journal.CurrentEntry;
 
                // The entry may be null here when the user has selected "New Window" or pressed Ctrl+N.
                // In this case the browser calls us on IPersistHistory::Save and then throws that data 
                // away.  Hopefully at some point in the future that saved data will be loaded in the new 
                // window via IPersistHistory::Load.  This unusual behavior is tracked in bug 1353584.
            } 

            if (entry != null)
            {
                info.title = entry.Name; 
                info.entryId = entry.Id;
            } 
            else 
            {
                info.title = _rbw.Value.Title; 
            }

            // We only use the base URI here because the travel log will validate a file URI when making a PIDL.
            // We use the URI stored in the JournalEntry, and the travel log doesn't care what the URI is, so 
            // duplicates don't matter.
            info.uri = BindUriHelper.UriToString(Uri); 
 
            MemoryStream saveStream = new MemoryStream();
            BinaryFormatter formatter = new BinaryFormatter(); 

            saveStream.Seek(0, SeekOrigin.Begin);
            object objectToSave = info.entryId;
 
            if (entireJournal)
            { 
                //Save the Journal and BaseUri also. We don't need BaseUri except for the xaml case 
                //since this is set specially for the container case (ssres scheme). Exe case
                //will pretty much set it to the exe path. For the xaml case it is set to the path 
                //of the first uri(eg BaseDir\page1.xaml) that was navigated to.
                //BaseDir/Subdir/page2.xaml is also considered to be in the same extent and when
                //we navigate back to the app from a webpage, the baseUri should still be BaseDir
                //not BaseDir/Subdir. We were setting the BaseDir from JournalEntry.Uri but we may 
                //end up setting BaseUri to BaseDir/Subdir which is not the same. So explicitly
                //persist BaseUri as well 
                BrowserJournal browserJournal = new BrowserJournal(journal, BindUriHelper.BaseUri); 
                objectToSave = browserJournal;
            } 

            new SecurityPermission(SecurityPermissionFlag.SerializationFormatter).Assert();
            try
            { 
                formatter.Serialize(saveStream, objectToSave);
            } 
            catch(Exception e) 
            {
                if(CriticalExceptions.IsCriticalException(e)) 
                {
                    throw;
                }
 
                // The application is shutting down and the exception would not be reported anyway.
                // This is here to help with debugging and failure analysis. 
                Invariant.Assert(false, "Failed to serialize the navigation journal: " + e); 
            }
            finally 
            {
                CodeAccessPermission.RevertAll() ;
            }
 
            info.saveByteArray = saveStream.ToArray();
            ((IDisposable)saveStream).Dispose(); 
 
            return info ;
        } 

        //CASRemoval:[SecurityPermission(SecurityAction.Assert, SerializationFormatter = true)]

        /// 
        ///     Critical as the delegate that this method invokes accesses critical data.
        /// 
        [SecurityCritical] 
        internal byte[] GetSaveHistoryBytes(bool persistEntireJournal, out int journalEntryId, out string uriString, out string titleString)
        { 
            SaveHistoryReturnInfo info = null ;

            if (Application.Current != null)
            { 
                info = ( SaveHistoryReturnInfo) Application.Current.Dispatcher.Invoke(
                                DispatcherPriority.Send, 
                                new DispatcherOperationCallback(_GetSaveHistoryBytesDelegate) , 
                                persistEntireJournal);
            } 

            if ( info != null )
            {
                journalEntryId = info.entryId; 
                uriString = info.uri;
                titleString = info.title; 
                return info.saveByteArray; 
            }
            else 
            {
                journalEntryId = 0;
                uriString = null;
                titleString = null; 
                return null;
            } 
        } 

        /// 
        ///     Critical as the delegate that this method invokes accesses critical data.
        ///
        [SecurityCritical]
        internal void LoadHistoryStream(MemoryStream loadStream, bool firstLoadFromHistory) 
        {
            if (Application.Current == null) 
            { 
                return;
            } 

            LoadHistoryStreamInfo info = new LoadHistoryStreamInfo();
            info.loadStream = loadStream ;
            info.firstLoadFromHistory = firstLoadFromHistory ; 

            Application.Current.Dispatcher.Invoke( 
                        DispatcherPriority.Send, 
                        new DispatcherOperationCallback(_LoadHistoryStreamDelegate),
                        info); 
        }

        private class LoadHistoryStreamInfo
        { 
            internal MemoryStream loadStream ;
            internal bool firstLoadFromHistory; 
        } 

        /// 
        ///     Critical as this method accesses critical data.
        ///
        [SecurityCritical]
        private object _LoadHistoryStreamDelegate( object arg ) 
        {
            Journal             journal     = null; 
            JournalEntry        entry       = null; 

            LoadHistoryStreamInfo info = (LoadHistoryStreamInfo) arg ; 

            if (IsShutdown() == true)
                return null;
 
            // Reset the memory stream pointer back to the begining and get the persisted object
            info.loadStream.Seek(0, System.IO.SeekOrigin.Begin); 
 
            object journaledObject = DeserializeJournaledObject(info.loadStream);
 
            //This is the very first load from history, so need to set the BaseUri and StartupUri.
            if (info.firstLoadFromHistory)
            {
                // Patch for WOSB 1834243: The journal does not get saved on Ctrl+N. Because of this, 
                // here we can get just an index, like in the 'else' case below.
                if(!(journaledObject is BrowserJournal)) 
                    return null; 

                BrowserJournal browserJournal = (BrowserJournal)journaledObject; 

                journal = browserJournal.Journal;
                entry = journal.CurrentEntry;
                if (entry == null) // See special case in _GetSaveHistoryBytesDelegate(). 
                {
                    entry = journal.GetGoBackEntry(); // could still be null 
                } 

                //This will create the frame to use for hosting 
                {
                    NavigationService navigationService = null;
                    navigationService = _rbw.Value.NavigationService;
                } 
                _rbw.Value.SetJournalForBrowserInterop(journal);
 
                //This should already be set for the container and exe cases. The former 
                //sets it to the transformed ssres scheme and we don't want to overwrite it.
                if (BindUriHelper.BaseUri == null) 
                {
                    BindUriHelper.BaseUri = browserJournal.BaseUri;
                }
 
                //
 
 

 
                Debug.Assert(Application.Current != null, "BrowserJournalingError: Application object should already be created");

                if (entry != null)
                { 
                    //Prevent navigations to StartupUri for history loads by canceling the StartingUp event
                    Application.Current.Startup += new System.Windows.StartupEventHandler(this.OnStartup); 
 
                    _rbw.Value.JournalNavigationScope.NavigateToEntry(entry);
                } 
                //else: fall back on navigating to StartupUri
            }
            else
            { 
                journal = _rbw.Value.Journal;
 
                int index = journal.FindIndexForEntryWithId((int)journaledObject); 

                Debug.Assert(journal[index].Id == (int)journaledObject, "BrowserJournalingError: Index retrieved from journal stream does not match index of journal entry"); 

                // Check whether the navigation is canceled.
                if (! _rbw.Value.JournalNavigationScope.NavigateToEntry(index))
                { 
                    // When the navigation is canceled, we want to notify browser to prevent the internal journal from
                    // getting out of sync with the browser's. 
                    // The exception will be caught by the interop layer and browser will cancel the navigation as a result. 

                    // If the navigation is initiated pragmatically by calling GoBack/Forward (comparing to user initiated 
                    // by clicking the back/forward button),  this will result in a managed exception at the call to ibcs.GoBack()
                    // in rbw.GoBackOverride(). rbw catches the exception when this happens.

                    throw new OperationCanceledException(); 
                }
            } 
 
            return null;
        } 

        /// 
        /// Critical - Asserts for Serialization permission to deserialize an object from the input stream.
        ///  
        [SecurityCritical]
        private object DeserializeJournaledObject(MemoryStream inputStream) 
        { 
            object deserialized = null;
            BinaryFormatter formatter = new BinaryFormatter(); 
            new System.Security.Permissions.SecurityPermission(SecurityPermissionFlag.SerializationFormatter).Assert();
            try
            {
                deserialized = formatter.Deserialize(inputStream); 
            }
            finally 
            { 
                CodeAccessPermission.RevertAssert();
            } 
            return deserialized;
        }

        // See if an App instance is currently loaded. 
        internal bool IsAppLoaded()
        { 
            return (Application.Current == null ? false : true); 
        }
 
        // Return the internal static variable _shutdown.
        internal bool IsShutdown()
        {
            return Application.IsShuttingDown; 
        }
 
        ///  
        /// Critical: Calls a critical ctor (ApplicationProxyInternal)
        ///  
        [SecurityCritical]
        internal static ApplicationProxyInternal CreateInDomain(AppDomain appDomain)
        {
            // Create an ApplicationProxyInternal in the new domain. 
            return appDomain.CreateInstanceAndUnwrap(
                                        Assembly.GetAssembly(typeof(ApplicationProxyInternal)).FullName, 
                                        typeof(ApplicationProxyInternal).FullName, 
                                        false,
                                        BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.CreateInstance, 
                                        null, null, null, null, null) as ApplicationProxyInternal;
        }

        ///  
        /// Critical:
        ///  1) Accesses _storageRoot, _container, _packageStream, _unmanagedStream 
        /// 
        /// TreatAsSafe:
        ///  1) Doesn't disclose _storageRoot, _container, _packageStream, 
        ///     _unmanagedStream
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal void Cleanup() 
        {
            if (Application.Current != null) 
            { 
                IBrowserCallbackServices bcs = Application.Current.BrowserCallbackServices;
                if (bcs != null) 
                {
                    Debug.Assert(!Application.IsApplicationObjectShuttingDown);
                    // Marshal.ReleaseComObject(bcs) has to be called so that the refcount of the
                    // native objects goes to zero for clean shutdown. But it should not be called 
                    // right away, because there may still be DispatcherOperations in the queue
                    // that will attempt to use IBCS, especially during downloading/activation. 
                    // Last, it can't be called with prioroty lower than Normal, because that's 
                    // the priority of Applicatoin.ShudownCallback(), which shuts down the
                    // Dispatcher. 
                    Application.Current.Dispatcher.BeginInvoke(
                        DispatcherPriority.Normal, new DispatcherOperationCallback(ReleaseBrowserCallback), bcs);
                }
            } 

            ServiceProvider = null; 
            ClearRootBrowserWindow(); 

            if (_storageRoot != null && _storageRoot.Value != null  ) 
            {
                _storageRoot.Value.Close();
            }
 
            // Due to the dependecies the following objects have to be released
            // in the following order: _document, DocumentManager, 
            // _packageStream, _unmanagedStream. 

            if (_document.Value is PackageDocument) 
            {
                // We are about to close the package ad remove it from the Preloaded Packages Store.
                // Let's make sure that the data structures are consistent. The package that we hold is
                // actually in the store under the URI that we think it should be using 
                Debug.Assert(((PackageDocument)_document.Value).Package ==
                                    PreloadedPackages.GetPackage(PackUriHelper.GetPackageUri(PackUriHelper.Create(Uri)))); 
 
                // We need to remove the Package from the PreloadedPackage storage,
                // so that potential future requests would fail in a way of returning a null (resource not found) 
                // rather then return a Package or stream that is already Closed
                PreloadedPackages.RemovePackage(PackUriHelper.GetPackageUri(PackUriHelper.Create(Uri)));

                ((PackageDocument)_document.Value).Dispose(); 
                _document.Value = null;
            } 
 
            if (_mimeType.Value == MimeType.Document)
            { 
                DocumentManager.CleanUp();
            }

            if (_packageStream.Value != null) 
            {
                _packageStream.Value.Close(); 
            } 

            if (_unmanagedStream.Value != null) 
            {
                Marshal.ReleaseComObject(_unmanagedStream.Value);
                _unmanagedStream = new SecurityCriticalData(null);
            } 
        }
 
        ///  
        /// Critical: Calls Marshal.ReleaseComObject(), which has a LinkDemand for unmanaged code.
        ///  
        [SecurityCritical]
        private object ReleaseBrowserCallback(object browserCallback)
        {
            Marshal.ReleaseComObject(browserCallback); 
            return null;
        } 
 
        #endregion Internal Methods
 
        //------------------------------------------------------
        //
        //  Internal Properties
        // 
        //------------------------------------------------------
        #region Internal Properties 
 
        internal RootBrowserWindowProxy RootBrowserWindowProxy
        { 
            get
            {
                if (_rbwProxy.Value == null)
                { 
                    CreateRootBrowserWindow();
                } 
                return _rbwProxy.Value; 
            }
        } 

        ///
        /// Critical as the setter stores the critical RBW reference
        /// 
        internal RootBrowserWindow RootBrowserWindow
        { 
            get 
            {
                return _rbw.Value; 
            }
            [SecurityCritical]
            private set
            { 
                _rbw.Value = value;
                if (value == null) 
                { 
                    _rbwProxy.Value = null;
                } 
                else
                {
                    _rbwProxy.Value = new RootBrowserWindowProxy(value);
 
                    if (_rectset == true)
                    { 
                        // If UIActivation already happened, set the size with 
                        // cached values.
                        Move(_windowRect); 
                        _rectset = false;
                    }

                    //Incase Show() was called before we had a chance to create the window 
                    //If the old and new values are the same, this will be a no-op anyway
                    Show(_show); 
                } 
            }
        } 

        internal OleCmdHelper OleCmdHelper
        {
            get 
            {
                if (Application.Current == null) 
                { 
                    return null;
                } 

                return (OleCmdHelper) Application.Current.Dispatcher.Invoke(
                DispatcherPriority.Send,
                (DispatcherOperationCallback) delegate(object unused) 
                {
                    // V3.5: Check for Application object shutting down only. 
                    // Consider to check for Browser shutting down. 
                    if (Application.IsApplicationObjectShuttingDown == true)
                        return null; 

                    if (_oleCmdHelper == null)
                    {
                        _oleCmdHelper = new OleCmdHelper(); 
                    }
                    return _oleCmdHelper; 
                }, 
                null);
            } 
        }

        /// 
        /// Critical: Returns a critical object, which can be used cross-AppDomain. 
        /// 
        internal static ApplicationProxyInternal Current 
        { 
            [SecurityCritical]
            get { return _proxyInstance; } 
        }

        /// 
        /// Critical: 
        ///  - sets _criticalUri which is critical
        ///  
        internal Uri Uri 
        {
            get 
            {
                return _criticalUri.Value;
            }
            [SecurityCritical] 
            private set
            { 
                _criticalUri.Value = value; 
                // We need to set these properties now, because there are times during the application's lifetime
                // when the source URI would be useful, but the ApplicationProxyInternal has come and gone. 
                SiteOfOriginContainer.BrowserSource = value;
                BrowserInteropHelper.SetSource(value);
            }
        } 

        ///  
        /// Critical: 
        ///  - sets SiteOfOriginContainer.DebugSeurityZoneURL which is critical
        ///  
        [SecurityCritical]
        internal void SetDebugSecurityZoneURL(Uri debugSecurityZoneURL)
        {
            SiteOfOriginContainer.DebugSecurityZoneURL = debugSecurityZoneURL; 
        }
 
        ///  
        ///     Critical - An external caller is setting the stream that we are using.  This is external
        ///                data from the web. 
        /// 
        internal object StreamContainer
        {
            [SecurityCritical] 
            set
            { 
                _unmanagedStream = new SecurityCriticalData(Marshal.GetObjectForIUnknown((IntPtr)value)); 
            }
        } 

        #endregion Internal Properties

        //----------------------------------------------------- 
        //
        //  Private Methods 
        // 
        //------------------------------------------------------
        #region Private Methods 

        private void OnStartup(Object sender, StartupEventArgs e)
        {
            //We listen to the Startup event only for history loads in which 
            //case we want to do our journaling load instead of StartupUri load
            e.PerformDefaultAction = false; 
            Application.Current.Startup -= new System.Windows.StartupEventHandler(this.OnStartup); 
        }
 
        /// 
        /// Will intialize the Package to be used by XpsViewer and register it with
        /// PreloadedPackages.
        ///  
        /// 
        /// Critical: 
        ///  1) asserts to create a CriticalFileToken  this is the first place we can 
        ///     validate the file is a container and it is the one provided by
        ///     the host (IE) 
        ///  2) sets the _packageStream value
        ///  3) sets the _document value
        ///  4) calls DocumentManager.CreateDefaultDocument(Uri *...) which is
        ///     now critical as the Uri is used by IAttachment for security 
        ///     decisions
        ///  5) adds a document package to PreloadedPackages 
        /// 
        /// TreatAsSafe:
        ///  1) the file for which we are asserting is SecurityCritical and 
        ///     appropriately protected, the Uri we use is critical (trusted)
        ///  1) it is also the intent of the user and the application to enable
        ///     editing of the file if they have the necessary ACLs and IRM
        ///     licenses so Write privileges are okay 
        ///  1) the document type we are enabling opening is an XpsDocument
        ///     which is not executable and trusted for use in PartialTrust 
        ///  2) _packageStream is set from data coming from critical for set 
        ///     source (trusted)
        ///  3) _document is set from data coming from critical for set source 
        ///     (trusted)
        ///  4) The source uri is critical and set by a trusted source (safe)
        ///  5) The document package is from _document which was set by a trusted source
        ///         The package is type of ZipPackage instantiated by XPS Viewer. 
        ///         The package is not going to be handed out from this API surface
        ///         and as such will be protected 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private void InitContainer() 
        {
            // using a local so it can not change during method execution
            Uri uri = Uri;
 
            PackageDocument doc;
 
            //--------------------------------------------------------------------------- 
            // Assign a temporary navigation delegate used for navigation in situations
            // where the RM client isn't installed before the application has started. 
            // This will be replaced by DocumentApplication once the application has initialized.
            MS.Internal.Documents.Application.NavigationHelper.Navigate = StartupNavigateDelegate;

            //--------------------------------------------------------------------------- 
            // Create PackageDocument from File (local or unc)
            if (uri.IsFile) 
            { 
                // create the CriticalFileToken
                CriticalFileToken fileToken = null; 
                string path = uri.LocalPath;
                new FileIOPermission(
                    FileIOPermissionAccess.Read
                    | FileIOPermissionAccess.Write, 
                    path).Assert();
                try 
                { 
                    fileToken = new CriticalFileToken(uri);
                } 
                finally
                {
                    FileIOPermission.RevertAssert();
                } 

                // create from file 
                doc = DocumentManager.CreateDefaultDocument(uri, fileToken); 
            }
            //--------------------------------------------------------------------------- 
            // Create PackageDocument from Stream (likely internet)
            else
            {
                // currently we do not support writing back to non-file 
                // sources, so we are limiting stream to "Read"
                _packageStream = new SecurityCriticalData( 
                    new ByteStream(_unmanagedStream.Value, FileAccess.Read)); 

                doc = DocumentManager.CreateDefaultDocument(uri, _packageStream.Value); 
            }

            //----------------------------------------------------------------------------
            // Open Package (may invoke WinForms UI) 
            try
            { 
                if (!DocumentManager.CreateDefault().Open(doc)) 
                {
                    throw new UnableToOpenDocumentException( 
                        SR.Get(SRID.DocumentApplicationUnableToOpenDocument));
                }
            }
            catch 
            {
                // on any failure, clean up the document before rethrowing 
                if (doc != null) 
                {
                    doc.Dispose(); 
                    doc = null;
                }
                throw;
            } 

            if ((doc != null) && (doc.Package != null)) 
            { 
                // after open document is valid
                _document.Value = doc; 

                // PreloadedPackages is a Package cache adding it prevents PackWebRequest
                // from making multiple web requests for the same container; doing so
                // would break XpsViewer's PackageDocument model and reduce the 
                // effectiveness of ByteRangeDownloader
                PreloadedPackages.AddPackage( 
                    PackUriHelper.GetPackageUri(PackUriHelper.Create(uri)), doc.Package); 
            }
        } 

        ///
        ///     Critical as this accesses critical data.
        ///     TreatAsSafe - as clearing the RBW is eliminating critical data - and considered safe. 
        ///
        [SecurityCritical, SecurityTreatAsSafe] 
        private void ClearRootBrowserWindow() 
        {
            RootBrowserWindow = null; 
        }

        /// 
        /// StartupNavigateDelegate is invoked during XPSViewer startup in the cases where 
        /// a navigation needs to be performed before the Application has started.
        /// (This happens when the user needs to install the RM client in order to view an 
        /// RM protected document - with user consent we will navigate to the RM install page.) 
        /// 
        /// Critical: 
        ///  1) Gets Uri which has path info we do not want to leak
        ///  2) Invokes an unsafe navigation to the specified uri via UnsafeLaunchBrowser
        /// 
        ///  
        /// 
        [SecurityCritical] 
        private static void StartupNavigateDelegate(SecurityCriticalData uri) 
        {
            // Make an unsafe navigation to the RM Client install page. 
            AppSecurityManager.UnsafeLaunchBrowser(uri.Value);
        }

        #endregion Private Methods 

        #region Private Properties 
 
        private IServiceProvider ServiceProvider
        { 
            set
            {
                _serviceProvider = value;
 
                if (Application.Current != null)
                { 
                    Application.Current.ServiceProvider = value; 
                }
            } 
        }

        #endregion
 
        //-----------------------------------------------------
        // 
        //  Private Fields 
        //
        //------------------------------------------------------ 
        #region Private Fields

        // Instance fields.
 
        // These are fields that moved from DocobjHost class so we can have a
        // unified way of calling for single vs multiple AppDomain scenarios. 
 
        ///
        /// Critical: We don't want an arbitrary window to be assigned here 
        ///   (even though only the real RBW can be created in PT).
        ///
        private SecurityCriticalDataForSet   _rbw;
 
        ///
        /// Critical for the same reason that _rbw is. 
        /// 
        private SecurityCriticalDataForSet _rbwProxy;
 
        private bool                _show;
        private OleCmdHelper        _oleCmdHelper;

        // The following variables are used to remember the window size until the window is created 
        // because the OLE SetRect/Show calls happen before the app and window are created internally
        Rect                        _windowRect; 
        bool                        _rectset; 

        private SecurityCriticalDataForSet _criticalUri; 
        SecurityCriticalDataClass _storageRoot = new SecurityCriticalDataClass(null);
        SecurityCriticalDataForSet _mimeType;
        IServiceProvider _serviceProvider ;
 
        /// 
        /// Critical: ApplicationProxyInternal can be used cross-AppDomain and implements 
        ///     critical functionality. 
        /// 
        [SecurityCritical] 
        private static ApplicationProxyInternal _proxyInstance;

        private const string FRAGMENT_MARKER = "#";
 
        #region XpsViewer (DocumentApplication) Specific
        ///  
        /// This is an unmanaged COM IStream that is provided by the byte range downloader 
        /// (progressive download) and comes from our unmanaged host.
        ///  
        /// 
        /// Critical:
        ///  1) this is a pointer to a security suppressed unmanaged stream, using it directly is
        ///     unsafe 
        ///  2) the data from this stream likely comes from the internet
        /// 
        /// Not Safe: 
        ///  1) although we did our best to protect from native exploits, no one is perfect and
        ///     the backing code is unmanaged 
        /// 
        SecurityCriticalData _unmanagedStream = new SecurityCriticalData(null);

        ///  
        /// This is a ByteWrapper a managed class that is an adapter from IStream to Stream.
        /// The stream it wraps is the _unmanagedStream. 
        ///  
        /// 
        /// Critical: 
        ///  1) we do not want this replaced with another stream after we have made security
        ///     decisions based on its contents (like mime type and start part)
        ///  2) this may be an EncryptedPackage which contains PII (Personally Identifiable
        ///     Information) in clear text; as such we want to audit use so information is 
        ///     not leaked
        /// 
        /// Not Safe: 
        ///  1) we want to audit it is set once
        ///  2) we want to audit for leaks 
        /// 
        SecurityCriticalData _packageStream = new SecurityCriticalData(null);

        ///  
        /// This contains many streams and packages that represent the current 'Package'
        /// for the XpsViewer. 
        ///  
        /// 
        /// Critical: 
        ///  1) none of this data can be effectively protected due to the visual tree
        ///     and Package.GetStream model currently in place protecting leaking of this
        ///     has been waived in a security review as it would have no net effect
        ///  2) based on the current hosting design we expect one 'Package' for the lifetime 
        ///     of the application, thus this should be audited such that it is set only once
        /// 
        /// Not Safe: 
        ///  2) we want to audit it is set once
        ///  
        // The Document has been weakly-typed to avoid PresentationFramework
        // having a type dependency on PresentationUI.  The perf impact of the weak
        // typed variables in this case was determined to be much less than forcing the load
        // of a new assembly when Assembly.GetTypes was called on PresentationFramework. 
        SecurityCriticalDataForSet _document;
        #endregion 
 
        #endregion Private Fields
 
        #region Private Structs
        /// 
        /// Holder for all things to be persisted in the BrowserJournal before we
        /// navigate away from the app 
        /// 
        [Serializable] 
        private struct BrowserJournal 
        {
            #region Constructors 
            internal BrowserJournal(Journal journal, Uri baseUri)
            {
                _journal = journal;
                _baseUri = baseUri; 
            }
            #endregion Constructors 
 
            #region Properties
            internal Journal Journal 
            {
                get { return _journal; }
            }
 
            internal Uri BaseUri
            { 
                get { return _baseUri; } 
            }
            #endregion Properties 

            #region Private Fields
            private Journal         _journal;
            private Uri             _baseUri; 
            #endregion Private Fields
        } 
        #endregion Private Structs 

        //------------------------------------------------------ 
        //
        //  Private Classes
        //
        //----------------------------------------------------- 
        #region Private Classes
        ///  
        /// Responsible for displaying a friendly message opposed to a callstack when we are 
        /// unable to open the document.
        ///  
        [Serializable]
        private class UnableToOpenDocumentException : Exception
        {
            internal UnableToOpenDocumentException(string message) : base(message) { } 

            ///  
            /// Required for serialization to marshal outside of our PT AppDomain. 
            /// 
            internal UnableToOpenDocumentException( 
                SerializationInfo info, StreamingContext context) : base(info, context) { }

            /// 
            /// Overriding ToString as we do not want to expose the callstack for this exception 
            /// as we are re-using exception handling to in this case to display and error but
            /// not an application fault message to the user. 
            ///  
            /// 
            public override string ToString() 
            {
                return this.Message;
            }
        } 

        ///  
        /// CrossDomainSerializableException is a simple wrapper around an Exception object 
        /// and is used only in ApplicationProxyInternal.Run() when instantiating
        /// an XPS Document instance. 
        ///
        /// This class does not demand for SerializationFormatter permissions (as is
        /// usually the case) in order to avoid a CLR bug (VSWhidbey 579013) wherein
        /// an exception marshalled across AppDomain boundaries will cause a 
        /// SecurityException due to an unmet demand for SerializationFormatter
        /// permissions. 
        /// 
        /// The CrossDomainSerializableException class is necessary because it is possible
        /// for the initialization of the document to throw (due to invalid document 
        /// content, for example) before we've switched over to running in the
        /// Avalon Dispatcher -- an exception thrown at that point will not be handled
        /// in our PT AppDomain, and will be marshaled, causing the SecurityException
        /// mentioned previously.  This is a bad support scenario, since any invalid 
        /// document (or related issue) will falsely appear to be a Security bug.  So
        /// this class wraps the actual exception thrown, and only exposes the output 
        /// from that exception's ToString method for error reporting purposes. 
        /// 
        [Serializable] 
        private sealed class CrossDomainSerializableException : Exception
        {
            internal CrossDomainSerializableException(Exception e)
            { 
                // Save the output of the wrapped exception's ToString().
                // NOTE: It is important that e.ToString() is invoked 
                // here (in Partial Trust) and not deferred to our 
                // ToString() override or other methods that
                // might be called outside of this AppDomain. 
                // This avoids a potential security issue where a
                // malicious Exception that overrides ToString() could
                // run arbitrary code in full trust.
                _wrappedToString = e.ToString(); 
            }
 
            ///  
            /// Deserializes an instance of this Exception object.
            /// This is required for marshalling across AppDomain boundaries. 
            /// 
            internal CrossDomainSerializableException(
                SerializationInfo info, StreamingContext context) : base(info, context)
            { 
                _wrappedToString = info.GetString("_wrappedToString");
            } 
 
            /// 
            /// Provides serialization information for this Exception object. 
            /// This is required for marshalling across AppDomain boundaries.
            /// 
            /// Critical - Calls the base.GetObjectData method (which linkdemands).
            ///            We are not ourselves demanding in order to avoid 
            ///            SecurityExceptions when marshalling across
            ///            domain boundaries.  (See class comment for more info.) 
            ///  
            /// 
            ///  
            /// 
            [SecurityCritical]
            public override void GetObjectData(SerializationInfo info, StreamingContext context)
            { 
                if (info == null)
                { 
                    throw new ArgumentNullException("info"); 
                }
 
                base.GetObjectData(info, context);

                // We are only serializing our _wrappedToString member.
                info.AddValue("_wrappedToString", _wrappedToString, typeof(String)); 
            }
 
            ///  
            /// Exposes the wrapped exception's ToString output.
            ///  
            /// 
            public override string ToString()
            {
                return _wrappedToString; 
            }
 
            private string _wrappedToString; 
        }
 
        #endregion Private Classes
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

                        

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