ProcessHost.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / xsp / System / Web / Hosting / ProcessHost.cs / 1599808 / ProcessHost.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Web.Hosting { 
    using System; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.Configuration;
    using System.Diagnostics.CodeAnalysis;
    using System.IO;
    using System.Runtime.InteropServices; 
    using System.Runtime.Remoting;
    using System.Security; 
    using System.Security.Permissions; 
    using System.Threading;
    using System.Web; 
    using System.Web.Configuration;
    using System.Web.Util;

 
    [ComImport, Guid("0ccd465e-3114-4ca3-ad50-cea561307e93"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IProcessHost { 
 
        void StartApplication(
                [In, MarshalAs(UnmanagedType.LPWStr)] 
                String appId,
                [In, MarshalAs(UnmanagedType.LPWStr)]
                String appPath,
                [MarshalAs(UnmanagedType.Interface)] out Object runtimeInterface); 

        void ShutdownApplication([In, MarshalAs(UnmanagedType.LPWStr)] String appId); 
 
        void Shutdown();
 
        void EnumerateAppDomains( [MarshalAs(UnmanagedType.Interface)] out IAppDomainInfoEnum appDomainInfoEnum);

    }
 
    //
    // App domain protocol manager 
    // Note that this doesn't provide COM interop 
    //
 
    public interface IAdphManager {

        void StartAppDomainProtocolListenerChannel(
            [In, MarshalAs(UnmanagedType.LPWStr)] String appId, 
            [In, MarshalAs(UnmanagedType.LPWStr)] String protocolId,
            IListenerChannelCallback listenerChannelCallback); 
 
        void StopAppDomainProtocolListenerChannel(
            [In, MarshalAs(UnmanagedType.LPWStr)] String appId, 
            [In, MarshalAs(UnmanagedType.LPWStr)] String protocolId,
            int listenerChannelId,
            bool immediate);
 
        void StopAppDomainProtocol(
            [In, MarshalAs(UnmanagedType.LPWStr)] String appId, 
            [In, MarshalAs(UnmanagedType.LPWStr)] String protocolId, 
            bool immediate);
    } 

    [ComImport, Guid("1cc9099d-0a8d-41cb-87d6-845e4f8c4e91"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IPphManager {
 
        void StartProcessProtocolListenerChannel(
            [In, MarshalAs(UnmanagedType.LPWStr)] String protocolId, 
            IListenerChannelCallback listenerChannelCallback); 

        void StopProcessProtocolListenerChannel( 
            [In, MarshalAs(UnmanagedType.LPWStr)] String protocolId,
            int listenerChannelId,
            bool immediate);
 
        void StopProcessProtocol(
            [In, MarshalAs(UnmanagedType.LPWStr)] String protocolId, 
            bool immediate); 
    }
 

    [ComImport, Guid("9d98b251-453e-44f6-9cec-8b5aed970129"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IProcessHostIdleAndHealthCheck {
 
        [return: MarshalAs(UnmanagedType.Bool)]
        bool IsIdle(); 
 
        void Ping(IProcessPingCallback callback);
    } 


    [ComImport, Guid("5BC9C234-6CD7-49bf-A07A-6FDB7F22DFFF"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IAppDomainInfo { 
        [return: MarshalAs(UnmanagedType.BStr)]
        string GetId(); 
 
        [return: MarshalAs(UnmanagedType.BStr)]
        string GetVirtualPath(); 

        [return: MarshalAs(UnmanagedType.BStr)]
        string GetPhysicalPath();
 
        [return: MarshalAs(UnmanagedType.I4)]
        int GetSiteId(); 
 
        [return: MarshalAs(UnmanagedType.Bool)]
        bool IsIdle(); 
    }

    [ComImport, Guid("F79648FB-558B-4a09-88F1-1E3BCB30E34F"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IAppDomainInfoEnum { 
        [return: MarshalAs(UnmanagedType.Interface)]
        IAppDomainInfo GetData(); 
 
        [return: MarshalAs(UnmanagedType.I4)]
        int Count(); 

        [return: MarshalAs(UnmanagedType.Bool)]
        bool MoveNext();
 
        void Reset();
    } 
 
    public class AppDomainInfoEnum : IAppDomainInfoEnum
    { 
        private AppDomainInfo[] _appDomainInfos;
        private int _curPos;

        internal AppDomainInfoEnum(AppDomainInfo[] appDomainInfos) 
        {
            _appDomainInfos = appDomainInfos; 
            _curPos = -1; 
        }
 
        public int Count()
        {
            return _appDomainInfos.Length;
        } 

        public IAppDomainInfo GetData() 
        { 
            return _appDomainInfos[_curPos];
        } 

        public bool MoveNext()
        {
            _curPos++; 

            if (_curPos >= _appDomainInfos.Length) 
            { 
                return false;
            } 

            return true;
        }
 
        public void Reset()
        { 
            _curPos = -1; 
        }
    } 

    public class AppDomainInfo : IAppDomainInfo
    {
        private string _id; 
        private string _virtualPath;
        private string _physicalPath; 
        private int _siteId; 
        private bool _isIdle;
 
        internal AppDomainInfo(string id, string vpath, string physPath, int siteId, bool isIdle)
        {
            _id = id;
            _virtualPath = vpath; 
            _physicalPath = physPath;
            _siteId = siteId; 
            _isIdle = isIdle; 
        }
 
        public string GetId()
        {
            return _id;
        } 

        public string GetVirtualPath() 
        { 
            return _virtualPath;
        } 

        public string GetPhysicalPath()
        {
            return _physicalPath; 
        }
 
        public int GetSiteId() 
        {
            return _siteId; 
        }

        public bool IsIdle()
        { 
            return _isIdle;
        } 
    } 

    ///////////////////////////////////////////////////////////////////////////// 
    // New for Dev10
    [ComImport, Guid("AE54F424-71BC-4da5-AA2F-8C0CD53496FC"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IApplicationPreloadManager {
        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId="Util", 
                         Justification="Name must match IIS COM interface.")]
        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId="0#Util", 
                         Justification="Name must match IIS COM interface.")] 
        void SetApplicationPreloadUtil(
            [In, MarshalAs(UnmanagedType.Interface)] IApplicationPreloadUtil preloadUtil); 

        void SetApplicationPreloadState(
            [In, MarshalAs(UnmanagedType.LPWStr)] string context,
            [In, MarshalAs(UnmanagedType.LPWStr)] string appId, 
            [In, MarshalAs(UnmanagedType.Bool)]  bool enabled);
    } 
 
    [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId="Util",
                     Justification="Name must match IIS COM interface.")] 
    [ComImport, Guid("940D8ADD-9E40-4475-9A67-2CDCDF57995C"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IApplicationPreloadUtil {

        [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId="1#", 
                         Justification="Parameter kind must match IIS COM interface.")]
        [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId="2#", 
                         Justification="Parameter kind must match IIS COM interface.")] 
        [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId="3#",
                         Justification="Parameter kind must match IIS COM interface.")] 
        void GetApplicationPreloadInfo(
            [In, MarshalAs(UnmanagedType.LPWStr)] string context,
            [Out, MarshalAs(UnmanagedType.Bool)] out bool enabled,
            [Out, MarshalAs(UnmanagedType.BStr)] out string startupObjType, 
            [Out, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] out string[] parametersForStartupObj);
 
        void ReportApplicationPreloadFailure( 
            [In, MarshalAs(UnmanagedType.LPWStr)] string context,
            [In, MarshalAs(UnmanagedType.U4)] int errorCode, 
            [In, MarshalAs(UnmanagedType.LPWStr)] string errorMessage);
    }

 
    /// 
    public sealed class ProcessHost : MarshalByRefObject, 
                                      IProcessHost, 
                                      IAdphManager, // process protocol handlers manager
                                      IPphManager,  // appdomain protocol handlers manager 
                                      IProcessHostIdleAndHealthCheck,
                                      IApplicationPreloadManager {
        private static Object _processHostStaticLock = new Object();
        private static ProcessHost _theProcessHost; 

        private IProcessHostSupportFunctions _functions; 
        private ApplicationManager _appManager; 
        private ProtocolsSection _protocolsConfig;
 
        // process protocol handlers by prot id
        private Hashtable _protocolHandlers = new Hashtable();
        private IApplicationPreloadUtil _preloadUtil = null;
 
        private System.Threading.Semaphore _preloadingThrottle = null;
 
        private ProtocolsSection ProtocolsConfig { 
            get {
                if (_protocolsConfig == null) { 
                    lock (this) {
                        if (_protocolsConfig == null) {

                            if (HttpConfigurationSystem.IsSet) { 
                                _protocolsConfig = RuntimeConfig.GetRootWebConfig().Protocols;
                            } else { 
                                Configuration c = WebConfigurationManager.OpenWebConfiguration(null); 
                                _protocolsConfig = (ProtocolsSection) c.GetSection("system.web/protocols");
                            } 

                        }
                    }
                } 
                return _protocolsConfig;
            } 
        } 

        // ctor only called via GetProcessHost 
        private ProcessHost(IProcessHostSupportFunctions functions) {
            try {
                // remember support functions
                _functions = functions; 

                // pass them along to the HostingEnvironment in the default domain 
                HostingEnvironment.SupportFunctions = functions; 

                // create singleton app manager 
                _appManager = ApplicationManager.GetApplicationManager();

                // For M3 we get the throttling limit from the registry.
                // Dev10\Beta1 work item 543420 is to investigate whether we need to get rid of the throttling 
                int maxPreloadConcurrency = (int)Misc.GetAspNetRegValue(null, "MaxPreloadConcurrency", 0);
                if (maxPreloadConcurrency > 0) { 
                    _preloadingThrottle = new System.Threading.Semaphore(maxPreloadConcurrency, maxPreloadConcurrency); 
                }
 

            }
            catch (Exception e) {
                using (new ProcessImpersonationContext()) { 
                    Misc.ReportUnhandledException(e, new string[]
                                                  { SR.GetString(SR.Cant_Create_Process_Host)}); 
                    Debug.Trace("internal", "ProcessHost::ctor failed with " + e.GetType().FullName + ": " + e.Message + "\r\n" + e.StackTrace); 
                }
                throw; 
            }
        }

        // ValidateType 
        //
        // Validate and Get the Type that is sent in 
        // 
        // Note: Because ProtocolElement is outside of our assembly we need to do
        //       that here, and because of that we need to hardcode the property 
        //       names!!
        //
        private Type ValidateAndGetType( ProtocolElement element,
                                         string          typeName, 
                                         Type            assignableType,
                                         string          elementPropertyName ) { 
            Type handlerType; 

            try { 
                 handlerType = Type.GetType(typeName, true /*throwOnError*/);
            }
            catch (Exception e) {
 
                PropertyInformation propInfo = null;
                string source = String.Empty; 
                int lineNum = 0; 

                if (element != null  && null != element.ElementInformation) { 
                    propInfo = element.ElementInformation.Properties[elementPropertyName];

                    if (null != propInfo) {
                        source = propInfo.Source; 
                        lineNum = propInfo.LineNumber;
                    } 
 
                }
 
                throw new ConfigurationErrorsException(
                            e.Message,
                            e,
                            source, 
                            lineNum);
            } 
 
            ConfigUtil.CheckAssignableType( assignableType, handlerType, element, elementPropertyName);
 
            return handlerType;
        }

        private Type GetAppDomainProtocolHandlerType(String protocolId) { 
            Type t = null;
 
            try { 
                // get app domaoin protocol handler type from config
                ProtocolElement configEntry = ProtocolsConfig.Protocols[protocolId]; 
                if (configEntry == null)
                    throw new ArgumentException(SR.GetString(SR.Unknown_protocol_id, protocolId));

                    t = ValidateAndGetType( configEntry, 
                                       configEntry.AppDomainHandlerType,
                                       typeof(AppDomainProtocolHandler), 
                                       "AppDomainHandlerType" ); 
            }
            catch (Exception e) { 
                using (new ProcessImpersonationContext()) {
                    Misc.ReportUnhandledException(e, new string[] {
                                              SR.GetString(SR.Invalid_AppDomain_Prot_Type)} );
                } 
            }
 
            return t; 
        }
 
        [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]
        public override Object InitializeLifetimeService() {
            return null; // never expire lease
        } 

        // called from ProcessHostFactoryHelper to get ProcessHost 
        internal static ProcessHost GetProcessHost(IProcessHostSupportFunctions functions) { 
            if (_theProcessHost == null) {
                lock (_processHostStaticLock) { 
                    if (_theProcessHost == null) {
                        _theProcessHost = new ProcessHost(functions);
                    }
                } 
            }
 
            return _theProcessHost; 
        }
 
        internal static ProcessHost DefaultHost {
            get {
                return _theProcessHost; // may be null
            } 
        }
 
        internal IProcessHostSupportFunctions SupportFunctions { 
            get {
                return _functions; 
            }
        }

        // 
        // IProcessHostProcessProtocolManager interface implementation
        // 
 
        // starts process protocol handler on demand
        public void StartProcessProtocolListenerChannel(String protocolId, IListenerChannelCallback listenerChannelCallback) { 
            try {
                if (protocolId == null)
                    throw new ArgumentNullException("protocolId");
 
                // validate protocol id
                ProtocolElement configEntry = ProtocolsConfig.Protocols[protocolId]; 
                if (configEntry == null) 
                    throw new ArgumentException(SR.GetString(SR.Unknown_protocol_id, protocolId));
 
                ProcessProtocolHandler protocolHandler = null;
                Type                   protocolHandlerType = null;

                protocolHandlerType = ValidateAndGetType( configEntry, 
                                                          configEntry.ProcessHandlerType,
                                                          typeof(ProcessProtocolHandler), 
                                                          "ProcessHandlerType" ); 

                lock (this) { 
                    // lookup or create protocol handler
                    protocolHandler = _protocolHandlers[protocolId] as ProcessProtocolHandler;

                    if (protocolHandler == null) { 
                        protocolHandler = (ProcessProtocolHandler)Activator.CreateInstance(protocolHandlerType);
                        _protocolHandlers[protocolId] = protocolHandler; 
                    } 

                } 

                // call the handler to start listenerChannel
                if (protocolHandler != null) {
                    protocolHandler.StartListenerChannel(listenerChannelCallback, this); 
                }
            } 
            catch (Exception e) { 
                using (new ProcessImpersonationContext()) {
                    Misc.ReportUnhandledException(e, new string[] { 
                                              SR.GetString(SR.Invalid_Process_Prot_Type)} );
                }
                throw;
            } 
        }
 
        public void StopProcessProtocolListenerChannel(String protocolId, int listenerChannelId, bool immediate) { 
            try {
                if (protocolId == null) 
                    throw new ArgumentNullException("protocolId");

                ProcessProtocolHandler protocolHandler = null;
 
                lock (this) {
                    // lookup protocol handler 
                    protocolHandler = _protocolHandlers[protocolId] as ProcessProtocolHandler; 
                }
 
                // call the handler to stop listenerChannel
                if (protocolHandler != null) {
                    protocolHandler.StopListenerChannel(listenerChannelId, immediate);
                } 
            }
            catch (Exception e) { 
                using (new ProcessImpersonationContext()) { 
                    Misc.ReportUnhandledException(e, new string[] {
                                              SR.GetString(SR.Failure_Stop_Listener_Channel)} ); 
                }
                throw;
            }
        } 

 
        public void StopProcessProtocol(String protocolId, bool immediate) { 
            try {
                if (protocolId == null) 
                    throw new ArgumentNullException("protocolId");

                ProcessProtocolHandler protocolHandler = null;
 
                lock (this) {
                    // lookup and remove protocol handler 
                    protocolHandler = _protocolHandlers[protocolId] as ProcessProtocolHandler; 

                    if (protocolHandler != null) { 
                        _protocolHandlers.Remove(protocolId);
                    }
                }
 
                if (protocolHandler != null) {
                    protocolHandler.StopProtocol(immediate); 
                } 
            }
            catch (Exception e) { 
                using (new ProcessImpersonationContext()) {
                    Misc.ReportUnhandledException(e, new string[] {
                                              SR.GetString(SR.Failure_Stop_Process_Prot)} );
                } 
                throw;
            } 
        } 

        // 
        // IAppDomainProtocolManager
        //

        // starts app domain protocol handler on demand (called by process protocol handler 

        public void StartAppDomainProtocolListenerChannel(String appId, String protocolId, IListenerChannelCallback listenerChannelCallback) { 
            try { 
                if (appId == null)
                    throw new ArgumentNullException("appId"); 
                if (protocolId == null)
                    throw new ArgumentNullException("protocolId");

                ISAPIApplicationHost appHost = CreateAppHost(appId, null); 

                // get app domaoin protocol handler type from config 
                Type handlerType = GetAppDomainProtocolHandlerType(protocolId); 

                AppDomainProtocolHandler handler = null; 

                LockableAppDomainContext ac = _appManager.GetLockableAppDomainContext(appId);

                lock (ac) { 
                    HostingEnvironmentParameters hostingParameters = new HostingEnvironmentParameters();
                    hostingParameters.HostingFlags = HostingEnvironmentFlags.ThrowHostingInitErrors; 
 
                    PreloadApplicationIfRequired(appId, appHost, hostingParameters, ac);
 
                    // call app manager to create the handler
                    handler = (AppDomainProtocolHandler)_appManager.CreateObjectInternal(
                        appId, handlerType, appHost, false /*failIfExists*/,
                        hostingParameters); 

                    // create a shim object that we can use for proxy unwrapping 
                    ListenerAdapterDispatchShim shim = (ListenerAdapterDispatchShim) 
                        _appManager.CreateObjectInternal(
                            appId, typeof(ListenerAdapterDispatchShim), appHost, false /*failIfExists*/, 
                            hostingParameters);

                    if (null != shim) {
                        shim.StartListenerChannel(handler, listenerChannelCallback); 

                        // remove the shim 
                        ((IRegisteredObject)shim).Stop(true); 
                    }
                    else { 
                        throw new HttpException(SR.GetString(SR.Failure_Create_Listener_Shim));
                    }
                }
            } 
            catch (Exception e) {
                using (new ProcessImpersonationContext()) { 
                    Misc.ReportUnhandledException(e, new string[] { 
                                              SR.GetString(SR.Failure_Start_AppDomain_Listener)} );
                } 
                throw;
            }
        }
 

        public void StopAppDomainProtocolListenerChannel(String appId, String protocolId, int listenerChannelId, bool immediate) { 
            try { 
                if (appId == null)
                    throw new ArgumentNullException("appId"); 
                if (protocolId == null)
                    throw new ArgumentNullException("protocolId");

                // get app domaoin protocol handler type from config 
                Type handlerType = GetAppDomainProtocolHandlerType(protocolId);
 
                AppDomainProtocolHandler handler = null; 

                LockableAppDomainContext ac = _appManager.GetLockableAppDomainContext(appId); 
                lock (ac) {
                    // call app manager to create the handler
                    handler = (AppDomainProtocolHandler)_appManager.GetObject(appId, handlerType);
                } 

                // stop the listenerChannel 
                if (handler != null) { 
                    handler.StopListenerChannel(listenerChannelId, immediate);
                } 
            }
            catch (Exception e) {
                using (new ProcessImpersonationContext()) {
                    Misc.ReportUnhandledException(e, new string[] { 
                                              SR.GetString(SR.Failure_Stop_AppDomain_Listener)} );
                } 
                throw; 
            }
        } 


        public void StopAppDomainProtocol(String appId, String protocolId, bool immediate) {
            try { 
                if (appId == null)
                    throw new ArgumentNullException("appId"); 
                if (protocolId == null) 
                    throw new ArgumentNullException("protocolId");
 
                // get app domaoin protocol handler type from config
                Type handlerType = GetAppDomainProtocolHandlerType(protocolId);

                AppDomainProtocolHandler handler = null; 

                LockableAppDomainContext ac = _appManager.GetLockableAppDomainContext(appId); 
                lock (ac) { 
                    // call app manager to create the handler
                    handler = (AppDomainProtocolHandler)_appManager.GetObject(appId, handlerType); 
                }

                // stop protocol
                if (handler != null) { 
                    handler.StopProtocol(immediate);
                } 
            } 
            catch (Exception e) {
                using (new ProcessImpersonationContext()) { 
                    Misc.ReportUnhandledException(e, new string[] {
                                              SR.GetString(SR.Failure_Stop_AppDomain_Protocol)} );
                }
                throw; 
            }
        } 
 
        public void StartApplication(String appId, String appPath, out Object runtimeInterface)
        { 
            try {
                if (appId == null)
                    throw new ArgumentNullException("appId");
                if (appPath == null) 
                    throw new ArgumentNullException("appPath");
 
                Debug.Assert(_functions != null, "_functions != null"); 

                runtimeInterface = null; 

                PipelineRuntime runtime = null;

                // 
                //  Fill app a Dictionary with 'binding rules' -- name value string pairs
                //  for app domain creation 
                // 

                // 


                if (appPath[0] == '.') {
                    System.IO.FileInfo file = new System.IO.FileInfo(appPath); 
                    appPath = file.FullName;
                } 
 
                if (!StringUtil.StringEndsWith(appPath, '\\')) {
                    appPath = appPath + "\\"; 
                }

                // Create new app host of a consistent type
                IApplicationHost appHost = CreateAppHost(appId, appPath); 

 
                // 
                // Create the AppDomain and a registered object in it
                // 
                LockableAppDomainContext ac = _appManager.GetLockableAppDomainContext(appId);

                lock (ac) {
                    // #1 WOS 1690249: ASP.Net v2.0: ASP.NET stress: 2nd chance exception: Attempted to access an unloaded AppDomain. 
                    // if an old AppDomain exists with a PipelineRuntime, remove it from
                    // AppManager._appDomains so that a new AppDomain will be created 
                    // #2 WOS 1977425: ASP.NET apps continue recycling after touching machine.config once - this used to initiate shutdown, 
                    // but that can cause us to recycle the app repeatedly if we initiate shutdown before IIS initiates shutdown of the
                    // previous app. 

                    _appManager.RemoveFromTableIfRuntimeExists(appId, typeof(PipelineRuntime));

 
                    // Preload (if required) the App Domain before letting the first request to be processed
                    PreloadApplicationIfRequired(appId, appHost, null, ac); 
 
                    try {
                        runtime = (PipelineRuntime)_appManager.CreateObjectInternal( 
                            appId,
                            typeof(PipelineRuntime),
                            appHost,
                            true /* failIfExists */, 
                            null /* default */ );
                    } 
                    catch (AppDomainUnloadedException) { 
                        // munch it so we can retry again
                    } 

                    if (null != runtime) {
                        runtime.SetThisAppDomainsIsapiAppId(appId);
                        runtime.StartProcessing(); 
                        runtimeInterface = new ObjectHandle(runtime);
                    } 
                } 
            }
            catch (Exception e) { 
                using (new ProcessImpersonationContext()) {
                    Misc.ReportUnhandledException(e, new string[] {
                                              SR.GetString(SR.Failure_Start_Integrated_App)} );
                } 
                throw;
            } 
        } 

 
        public void ShutdownApplication(String appId) {
            try {
                // call into app manager
                _appManager.ShutdownApplication(appId); 
            }
            catch (Exception e) { 
                using (new ProcessImpersonationContext()) { 
                    Misc.ReportUnhandledException(e, new string[] {
                                              SR.GetString(SR.Failure_Stop_Integrated_App)} ); 
                }
                throw;
            }
        } 

        public void Shutdown() { 
            try { 
                // collect all protocols under lock
                ArrayList protocolList = new ArrayList(); 
                int       refCount = 0;

                lock (this) {
                    // lookup protocol handler 
                    foreach (DictionaryEntry e in _protocolHandlers) {
                        protocolList.Add(e.Value); 
                    } 

                    _protocolHandlers = new Hashtable(); 
                }

                // stop all process protocols outside of lock
                foreach (ProcessProtocolHandler p in protocolList) { 
                    p.StopProtocol(true);
                } 
 
                // call into app manager to shutdown
                _appManager.ShutdownAll(); 


                // SupportFunctions interface provided by native layer
                // must be released now. 
                // Otherwise the release of the COM object will have
                // to wait for GC. Native layer assumes that after 
                // returning from Shutdown there is no reference 
                // to the native objects from ProcessHost.
                // 
                do {
                    refCount = Marshal.ReleaseComObject( _functions );
                } while( refCount != 0 );
 
            }
            catch (Exception e) { 
                using (new ProcessImpersonationContext()) { 
                    Misc.ReportUnhandledException(e, new string[] {
                                              SR.GetString(SR.Failure_Shutdown_ProcessHost), e.ToString()} ); 
                }
                throw;
            }
        } 

        public void EnumerateAppDomains( out IAppDomainInfoEnum appDomainInfoEnum ) 
        { 
            try {
                ApplicationManager appManager = ApplicationManager.GetApplicationManager(); 
                AppDomainInfo [] infos;

                infos = appManager.GetAppDomainInfos();
 
                appDomainInfoEnum = new AppDomainInfoEnum(infos);
            } 
            catch (Exception e) { 
                using (new ProcessImpersonationContext()) {
                    Misc.ReportUnhandledException(e, new string[] { 
                                              SR.GetString(SR.Failure_AppDomain_Enum)} );
                }
                throw;
            } 
        }
 
        // IProcessHostIdleAndHealthCheck interface implementation 
        public bool IsIdle() {
            bool result = false; 

            try {
                result = _appManager.IsIdle();
            } 
            catch (Exception e) {
                using (new ProcessImpersonationContext()) { 
                    Misc.ReportUnhandledException(e, new string[] { 
                                              SR.GetString(SR.Failure_PMH_Idle)} );
                } 
                throw;
            }

            return result; 
        }
 
 
        public void Ping(IProcessPingCallback callback) {
            try { 
                if (callback != null)
                    _appManager.Ping(callback);
            }
            catch (Exception e) { 
                using (new ProcessImpersonationContext()) {
                    Misc.ReportUnhandledException(e, new string[] { 
                                              SR.GetString(SR.Failure_PMH_Ping)} ); 
                }
                throw; 
            }
        }

        private ISAPIApplicationHost CreateAppHost(string appId, string appPath) { 

            // 
            // if we have a null physical path, we need 
            // to use the PMH to resolve it
            // 
            if (String.IsNullOrEmpty(appPath)) {
                string virtualPath;
                string physicalPath;
                string siteName; 
                string siteID;
 
                _functions.GetApplicationProperties( 
                        appId,
                        out virtualPath, 
                        out physicalPath,
                        out siteName,
                        out siteID);
 
                //
                // make sure physical app path ends with '\\' and virtual does not 
                // 
                if (!StringUtil.StringEndsWith(physicalPath, '\\')) {
                    physicalPath = physicalPath + "\\"; 
                }

                Debug.Assert( !String.IsNullOrEmpty(physicalPath), "!String.IsNullOrEmpty(physicalPath)");
                appPath = physicalPath; 
            }
 
            // 
            // Create a new application host
            // This needs to be a coherent type across all 
            // protocol types so that we get a consistent
            // environment regardless of which protocol initializes first
            //
            ISAPIApplicationHost appHost = new 
                ISAPIApplicationHost(
                        appId, 
                        appPath, 
                        false, /* validatePhysicalPath */
                        _functions 
                        );


            return appHost; 
        }
 
        public void SetApplicationPreloadUtil(IApplicationPreloadUtil applicationPreloadUtil) { 

            // Do not allow setting PreloadUtil again if it has already has been set 
            if (_preloadUtil != null) {
                throw new InvalidOperationException(SR.GetString(SR.Failure_ApplicationPreloadUtil_Already_Set));
            }
 
            _preloadUtil = applicationPreloadUtil;
        } 
 
        public void SetApplicationPreloadState(string context, string appId, bool enabled) {
            // Check params 
            if (String.IsNullOrEmpty(context)) {
                throw ExceptionUtil.ParameterNullOrEmpty("context");
            }
            if (String.IsNullOrEmpty(appId)) { 
                throw ExceptionUtil.ParameterNullOrEmpty("appId");
            } 
 
            // _preloadUtil must be not null if we have an application preload enabled
            if (enabled && _preloadUtil == null) { 
                throw new ArgumentException(SR.GetString(SR.Invalid_Enabled_Preload_Parameter), "enabled");
            }

            LockableAppDomainContext ac = _appManager.GetLockableAppDomainContext(appId); 

            lock (ac) { 
                ac.PreloadContext = context; 
                if (enabled) {
                    PreloadApplicationIfRequired(appId, null, null, ac); 
                }
            }
        }
 
        internal static void PreloadApplicationIfNotShuttingdown (string appId, LockableAppDomainContext ac) {
            if (ProcessHost.DefaultHost != null && UnsafeIISMethods.MgdHasConfigChanged()) { 
                // Start the new app on another thread instead of hijacking the current app unloading thread 
                ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object o) {
                    lock (ac) { 
                        try {
                            // NOTE: we don't know what HostingEnvironmentParameters were passed to our previous application instance
                            // so we pass null (default for HTTP activation). We could have cached it in ApplicationContext if needed
                            ProcessHost.DefaultHost.PreloadApplicationIfRequired(appId, null, null, ac); 
                        }
                        catch (Exception e) { 
                            ProcessHost.DefaultHost.ReportApplicationPreloadFailureWithAssert( 
                                ac.PreloadContext,
                                HResults.E_FAIL, 
                                Misc.FormatExceptionMessage(
                                    e, new string[] {
                                        SR.GetString(SR.Failure_Preload_Application_Initialization)}));
                        } 
                    }
                })); 
            } 
        }
 
        // New for Dev10.
        // creates a new AppDomain, preloads and calls user code in it
        internal void PreloadApplicationIfRequired(
                string appId, 
                IApplicationHost appHostParameter,
                HostingEnvironmentParameters hostingParameters, 
                LockableAppDomainContext ac) { 

            // NOTE1:  Must never be called under lock (_appManager) 
            // NOTE2:  Must always be called under lock (ac)

            // We only need to preload if auto start is enabled and we have not already preloaded (i.e. HostingEnvironment doesn't exist)
            if (_preloadUtil == null || ac.PreloadContext == null || ac.HostEnv != null) { 
                return;
            } 
 
            // Get and verify the preload parameters
            string preloadObjTypeName; 
            string[] paramsForStartupObj;
            bool stillEnabled;

            GetApplicationPreloadInfoWithAssert(ac.PreloadContext, out stillEnabled, out preloadObjTypeName, out paramsForStartupObj); 

            // Dev10: 782385	ASP.NET autostart implementation should be tolerant of empty string for the provider type 
            if (!stillEnabled || String.IsNullOrEmpty(preloadObjTypeName)) { 
                return;
            } 

            // Ready to load the App Domain
            if (_preloadingThrottle != null) {
                // Throttle the number of simultaneously created appdomains 
                _preloadingThrottle.WaitOne();
            } 
 
            try {
 
                // Create the app-host and start a new App Domain
                IApplicationHost appHost = (appHostParameter == null) ? CreateAppHost(appId, null) : appHostParameter;

                // call app manager to create the PreloadHost 
                PreloadHost preloadHostObj = (PreloadHost)_appManager.CreateObjectInternal(
                    appId, 
                    typeof(PreloadHost), 
                    appHost,
                    true /*failIfExists*/, 
                    hostingParameters);

                // Dev10 858421:  File sharing violations on config files cause unnecessary process shutdown in autostart mode
                // 
                // There are race conditions between whoever modifies the config files
                // and the application config system that reads from the config files 
                // These file sharing violation lead to random application initialization failures 
                // Service auto-start mode is more vulnerable to these sharing violations because
                // it starts a new app domain as soon as the file change notification is received 
                // and when an error occurs IIS recycles the whole app pool rather than a particular app
                //
                // In most cases that we see in stress the inner most exception is System.IO.IOException
                // so if we see this exception we will give it another try before 
                // reporting the errors to IIS and recycling the process
                // 
 
                // Check for I/O exceptions during initialization and retry one time
                Exception appInitEx = preloadHostObj.InitializationException; 
                if (GetInnerMostException(appInitEx) is IOException) {
                    try {
                        // prevent ApplicationManager.HostingEnvironmentShutdownInitiated from attempting to preload again
                        ac.RetryingPreload = true; 
                        // shutdown old hosting environment
                        ac.HostEnv.InitiateShutdownInternal(); 
                    } 
                    finally {
                        ac.RetryingPreload = false; 
                    }

                    // Create the app-host and start a new App Domain
                    appHost = (appHostParameter == null) ? CreateAppHost(appId, null) : appHostParameter; 

                    // call app manager to create the PreloadHost 
                    preloadHostObj = (PreloadHost)_appManager.CreateObjectInternal( 
                        appId,
                        typeof(PreloadHost), 
                        appHost,
                        true /*failIfExists*/,
                        hostingParameters);
 
                    appInitEx = preloadHostObj.InitializationException;
                } 
 
                // Check again for initialization exception and tell IIS to recycle the process
                if (appInitEx != null) { 
                    ReportApplicationPreloadFailureWithAssert(
                        ac.PreloadContext,
                        HResults.E_FAIL,
                        Misc.FormatExceptionMessage( 
                            appInitEx, new string[] {
                                SR.GetString(SR.Failure_Preload_Application_Initialization)} )); 
 
                    // we must throw if preload fails because we cannot allow the normal
                    // startup path to continue and attempt to create a HostingEnvironment 
                    throw appInitEx;
                }

                // Call preload code in the App Domain 
                try {
                    preloadHostObj.CreateIProcessHostPreloadClientInstanceAndCallPreload(preloadObjTypeName, paramsForStartupObj); 
                } 
                catch (Exception e) {
                    // report errors 
                    ReportApplicationPreloadFailureWithAssert(
                        ac.PreloadContext,
                        HResults.E_FAIL,
                        Misc.FormatExceptionMessage( 
                            e, new string[] {
                                SR.GetString(SR.Failure_Calling_Preload_Provider)} ).ToString()); 
 
                    throw;
                } 
            }
            finally {
                if (_preloadingThrottle != null) {
                    _preloadingThrottle.Release(); 
                }
            } 
 
        }
 
        private static Exception GetInnerMostException(Exception e) {
            if (e == null) {
                return null;
            } 
            while (e.InnerException != null) {
                e = e.InnerException; 
            } 
            return e;
        } 

        [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
        private void GetApplicationPreloadInfoWithAssert(
                string context, out bool enabled, out string startupObjType, out string[] parametersForStartupObj) { 
            _preloadUtil.GetApplicationPreloadInfo(context, out enabled, out startupObjType, out parametersForStartupObj);
        } 
 
        [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
        private void ReportApplicationPreloadFailureWithAssert(string context, int errorCode, string errorMessage) { 
            _preloadUtil.ReportApplicationPreloadFailure(context, errorCode, errorMessage);
        }
    }
 
    internal sealed class ListenerAdapterDispatchShim : MarshalByRefObject, IRegisteredObject {
 
        void IRegisteredObject.Stop(bool immediate) { 
            HostingEnvironment.UnregisterObject(this);
        } 

        // this should run in an Hosted app domain (not in the default domain)
        internal void StartListenerChannel( AppDomainProtocolHandler handler, IListenerChannelCallback listenerCallback ) {
            Debug.Assert( HostingEnvironment.IsHosted, "HostingEnvironment.IsHosted" ); 
            Debug.Assert( null != handler, "null != handler" );
 
            IListenerChannelCallback unwrappedProxy = MarshalComProxy(listenerCallback); 

            Debug.Assert(null != unwrappedProxy, "null != unwrappedProxy"); 
            if (null != unwrappedProxy && null != handler) {
                handler.StartListenerChannel(unwrappedProxy);
            }
        } 

        internal IListenerChannelCallback MarshalComProxy(IListenerChannelCallback defaultDomainCallback) { 
            IListenerChannelCallback localProxy = null; 

            // get the underlying COM object 
            IntPtr pUnk = Marshal.GetIUnknownForObject(defaultDomainCallback);

            // this object isn't a COM object
            if (IntPtr.Zero == pUnk) { 
                return null;
            } 
 
            IntPtr ppv = IntPtr.Zero;
            try { 
                // QI it for the interface
                Guid g = typeof(IListenerChannelCallback).GUID;

                int hresult = Marshal.QueryInterface(pUnk, ref g, out ppv); 
                if (hresult < 0)  {
                    Marshal.ThrowExceptionForHR(hresult); 
                } 

                // create a RCW we can hold onto in this domain 
                // this bumps the ref count so we can drop our refs on the raw interfaces
                localProxy = (IListenerChannelCallback)Marshal.GetObjectForIUnknown(ppv);
            }
            finally { 
                // drop our explicit refs and keep the managed instance
                if (IntPtr.Zero != ppv) { 
                    Marshal.Release(ppv); 
                }
                if (IntPtr.Zero != pUnk) { 
                    Marshal.Release(pUnk);
                }
            }
 
            return localProxy;
        } 
 
    }
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

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