File: src\Shared\MS\Internal\SecurityHelper.cs
Project: wpf\PresentationFramework.csproj (PresentationFramework)
/***************************************************************************\
*
* File: SecurityHelper.cs
*
* Purpose:  Helper functions that require elevation but are safe to use.
*
* Copyright (C) 2004 by Microsoft Corporation.  All rights reserved.
*
\***************************************************************************/
 
// The SecurityHelper class differs between assemblies and could not actually be
//  shared, so it is duplicated across namespaces to prevent name collision.
// [Microsoft, June'09] This duplication seems hardly necessary now. We should continue
// trying to reduce it by pushing things from Framework to Core (whenever it makes sense).
#if WINDOWS_BASE
namespace MS.Internal.WindowsBase
#elif PRESENTATION_CORE
using MS.Internal.PresentationCore;
namespace MS.Internal // Promote the one from PresentationCore as the default to use.
#elif PRESENTATIONFRAMEWORK
namespace MS.Internal.PresentationFramework
#elif PBTCOMPILER
namespace MS.Internal.PresentationBuildTasks
#elif REACHFRAMEWORK
namespace MS.Internal.ReachFramework
#elif DRT
namespace MS.Internal.Drt
#else
#error Class is being used from an unknown assembly.
#endif
{
    using System;
    using System.Globalization;     // CultureInfo
    using System.Security;
    using System.Security.Permissions;
    using System.Net; // WebPermission.
    using System.ComponentModel;
    using System.Security.Policy;
    using System.Runtime.InteropServices;
    using Microsoft.Win32;
    using System.Windows.Markup;
    using System.Diagnostics.CodeAnalysis;
 
 
#if !PBTCOMPILER
    using MS.Win32;
    using System.IO.Packaging;
#endif
 
#if WINDOWS_BASE || PRESENTATIONUI
    using MS.Internal.Permissions;
#endif
#if PRESENTATION_CORE
using MS.Internal.AppModel;
using MS.Internal.Permissions;
#endif
 
#if PRESENTATIONFRAMEWORK_ONLY
    using MS.Internal.Permissions ;
    using System.Diagnostics;
    using System.Windows;
    using MS.Internal.Utility;      // BindUriHelper
    using MS.Internal.AppModel;
#endif
 
#if REACHFRAMEWORK
    using MS.Internal.Utility;
#endif
#if WINDOWS_BASE
    // This existed originally to allow FontCache service to 
    // see the WindowsBase variant of this class. We no longer have
    // a FontCache service, but over time other parts of WPF might
    // have started to depend on this, so we leave it as-is for 
    // compat. 
    [FriendAccessAllowed] 
#endif
 
 
internal static class SecurityHelper
    {
#if !PBTCOMPILER
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// Safe     - The method denies the caller access to the full exception object.
        /// </SecurityNote>
#if REACHFRAMEWORK
        [SecurityCritical]
#else        
        [SecuritySafeCritical]
#endif        
        internal static bool CheckUnmanagedCodePermission()
        {
            try
            {
                SecurityHelper.DemandUnmanagedCode();
            }
            catch(SecurityException )
            {
                return false ;
            }
 
            return true;
        }
 
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandUnmanagedCode()
        {
            if(_unmanagedCodePermission == null)
            {
                _unmanagedCodePermission = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode);
            }
            _unmanagedCodePermission.Demand();
        }
        static SecurityPermission _unmanagedCodePermission = null;
#endif  //  !PBTCOMPILER
 
#if PRESENTATION_CORE

        ///<summary>
        /// Create a UserInitiatedRoutedEvent permission.
        /// Separate helper exists to make it easy to change what the permission is.
        ///</summary>
        ///<SecurityNote>
        ///  Critical: Returns a permission object, which can be misused.
        ///</SecurityNote>
        [SecurityCritical]
        internal static CodeAccessPermission CreateUserInitiatedRoutedEventPermission()
        {
            if(_userInitiatedRoutedEventPermission == null)
            {
                _userInitiatedRoutedEventPermission = new UserInitiatedRoutedEventPermission();
            }
            return _userInitiatedRoutedEventPermission;
        }
 
        ///<summary>
        /// Check whether the call stack has the permissions needed for UserInitiated RoutedEvents.
        /// </summary>
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// Safe     - The method denies the caller access to the full exception object.
        /// </SecurityNote>
        [SecuritySafeCritical]
        internal static bool CallerHasUserInitiatedRoutedEventPermission()
        {
            try
            {
                CreateUserInitiatedRoutedEventPermission().Demand();
            }
            catch (SecurityException)
            {
                return false;
            }
            return true;
        }
 
        static UserInitiatedRoutedEventPermission _userInitiatedRoutedEventPermission = null;
 
#endif // PRESENTATION_CORE
 
#if PRESENTATIONFRAMEWORK
 
        /// <SecurityNote>
        /// Critical: This code throws an exception if someone sets value to be true and we are in partial trust
        /// TreatAsSafe: The only reason we mark this as critical is to track code
        /// </SecurityNote>
        [SecurityCritical, SecurityTreatAsSafe]
        internal static void ThrowExceptionIfSettingTrueInPartialTrust(ref bool value)
        {
            if (value == true && !SecurityHelper.CheckUnmanagedCodePermission())
            {
                value = false;
                throw new SecurityException(SR.Get(SRID.SecurityExceptionForSettingSandboxExternalToTrue));
            }
        }
 
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandWebBrowserPermission()
        {
            CachedWebBrowserPermission.Demand();
        }
 
        ///<SecurityNote>
        ///  Critical: Returns a permission object, which can be misused.
        ///</SecurityNote>
        internal static WebBrowserPermission CachedWebBrowserPermission
        {
            [SecurityCritical]
            get
            {
                if (_webBrowserPermission == null)
                {
                    _webBrowserPermission = new WebBrowserPermission(PermissionState.Unrestricted);
                }
                return _webBrowserPermission;
            }
        }
        static WebBrowserPermission _webBrowserPermission;
 
        ///<summary>
        /// Check whether the call stack has the permissions needed for WebBrowser.
        /// Optimization: false is returned if the AppDomain's permission grant does not include the
        ///   WebBrowserPermission. This preliminary check will defeat an Assert on the callstack, but it
        ///   avoids the SecurityException in PT when the full WB permission is not granted.
        /// </summary>
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// Safe     - The method denies the caller access to the full exception object.
        /// </SecurityNote>
        [SecuritySafeCritical]
        internal static bool CallerAndAppDomainHaveUnrestrictedWebBrowserPermission()
        {
            if (!MS.Internal.SecurityHelper.AppDomainHasPermission(CachedWebBrowserPermission))
                return false;
            try
            {
                SecurityHelper.DemandWebBrowserPermission();
            }
            catch (SecurityException)
            {
                return false;
            }
            return true;
        }
 
        ///<summary>
        /// Check to see if we have User initiated navigation permission.
        ///</summary>
        /// <returns>true if call stack has UserInitiatedNavigation permission</returns>
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// Safe     - The method denies the caller access to the full exception object.
        /// </SecurityNote>
        [SecuritySafeCritical]
        internal static bool CallerHasUserInitiatedNavigationPermission()
        {
            try
            {
                CreateUserInitiatedNavigationPermission();
                _userInitiatedNavigationPermission.Demand();
            }
            catch (SecurityException)
            {
                return false;
            }
            return true;
        }
 
 
        ///<summary>
        /// Create a UserInitiatedNavigation permission.
        /// Separate helper exists to make it easy to change what the permission is.
        ///</summary>
        ///<SecurityNote>
        ///  Critical: Returns a permission object, which can be misused.
        ///</SecurityNote>
        [SecurityCritical]
        internal static CodeAccessPermission CreateUserInitiatedNavigationPermission()
        {
            if(_userInitiatedNavigationPermission == null)
            {
                _userInitiatedNavigationPermission = new UserInitiatedNavigationPermission();
            }
            return _userInitiatedNavigationPermission;
        }
        static UserInitiatedNavigationPermission _userInitiatedNavigationPermission = null;
 
        /// <summary>
        /// Demands for permissions needed to construct the PrintDialog in
        /// full trust mode and/or access full trust properties from dialog.
        /// </summary>
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandPrintDialogPermissions()
        {
            if(_defaultPrintingPermission == null)
            {
                _defaultPrintingPermission = SystemDrawingHelper.NewDefaultPrintingPermission();
            }
            _defaultPrintingPermission.Demand();
        }
        static CodeAccessPermission _defaultPrintingPermission = null;
 
        ///<summary>
        /// Check to see if we have Reflection permission to create types and access members.
        ///</summary>
        /// <returns>true if call stack has Reflection permission</returns>
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// Safe     - The method denies the caller access to the full exception object.
        /// </SecurityNote>
        [SecuritySafeCritical]
        internal static bool CallerHasMemberAccessReflectionPermission()
        {
            try
            {
                if (_reflectionPermission == null)
                {
                    _reflectionPermission = new ReflectionPermission(ReflectionPermissionFlag.MemberAccess);
                }
                _reflectionPermission.Demand();
            }
            catch (SecurityException)
            {
                return false;
            }
 
            return true;
        }
        static ReflectionPermission _reflectionPermission = null;
 
#endif
 
#if PRESENTATION_CORE

        ///<summary>
        /// Check to see if the caller is fully trusted.
        ///</summary>
        /// <returns>true if call stack has unrestricted permission</returns>
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// Safe     - The method denies the caller access to the full exception object.
        /// </SecurityNote>
        [SecuritySafeCritical]
        internal static bool IsFullTrustCaller()
        {
            try
            {
                if (_fullTrustPermissionSet == null)
                {
                    _fullTrustPermissionSet = new PermissionSet(PermissionState.Unrestricted);
                }
                _fullTrustPermissionSet.Demand();
            }
            catch (SecurityException)
            {
                return false;
            }
 
            return true;
        }
        static PermissionSet _fullTrustPermissionSet = null;
 
        ///<summary>
        /// Return true if the caller has the correct permission set to get a folder
        /// path.
        ///</summary>
        ///<remarks>
        /// This function exists solely as a an optimazation for the debugger scenario
        ///</remarks>
        /// <SecurityNote>
        ///    Critical: This code extracts the permission set associated with an appdomain by elevating
        ///    TreatAsSafe: The information is not exposed
        /// </SecurityNote>
        [SecuritySafeCritical]
        //
        internal static bool CallerHasPermissionWithAppDomainOptimization(params IPermission[] permissionsToCheck)
        {
            // in case of passing null return true
            if (permissionsToCheck == null)
                return true;
            PermissionSet psToCheck = new PermissionSet(PermissionState.None);
            for ( int i = 0 ; i < permissionsToCheck.Length ; i++ )
            {
                psToCheck.AddPermission(permissionsToCheck[i]);
            }
            PermissionSet permissionSetAppDomain = AppDomain.CurrentDomain.PermissionSet;
            if (psToCheck.IsSubsetOf(permissionSetAppDomain))
            {
                return true;
            }
            return false;
        }
 
        /// <summary> Enables an efficient check for a specific permisison in the AppDomain's permission grant
        /// without having to catch a SecurityException in the case the permission is not granted.
        /// <summary>
        /// <SecurityNote>
        /// Caveat: This is not a generally valid substitute for doing a full Demand. The main cases not
        /// covered are:
        ///   1) call from PT AppDomain into full-trust one;
        ///   2) captured PT callstack (via ExecutionContext) from another thread or context. Our Dispatcher
        ///     does this.
        ///
        /// Critical: Accesses the Critical AppDomain.PermissionSet, which might contain sensitive information
        ///     such as file paths.
        /// Safe: Does not expose the permission object to the caller.
        /// </SecurityNote>
        [SecuritySafeCritical]
        internal static bool AppDomainHasPermission(IPermission permissionToCheck)
        {
            Invariant.Assert(permissionToCheck != null);
            PermissionSet psToCheck = new PermissionSet(PermissionState.None);
            psToCheck.AddPermission(permissionToCheck);
            return psToCheck.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet);
        }
 
        /// <SecurityNote>
        /// Critical: Elevates to extract the AppDomain BaseDirectory and returns it, which is sensitive information.
        /// </SecurityNote>
        [SecurityCritical]
        internal static Uri GetBaseDirectory(AppDomain domain)
        {
            Uri appBase = null;
            new FileIOPermission(PermissionState.Unrestricted).Assert();// BlessedAssert
            try
            {
                appBase = new Uri(domain.BaseDirectory);
            }
            finally
            {
                FileIOPermission.RevertAssert();
            }
            return( appBase );
        }
 
        //This code path is only executed if we are trying to get to http content from https
        internal static Uri ExtractUriForClickOnceDeployedApp()
        {
            // This api returns the location from where an app was deployed. In case of browser hosted apps
            // there are no elevations and this information is safe to return.
            // In case of non browserhosted scenarios this will trigger a demand since we do not assert to get
            // this information in the code below
            return    SiteOfOriginContainer.SiteOfOriginForClickOnceApp;
        }
 
         //This code path is only executed if we are trying to get to http content from https
        /// <SecurityNote>
        ///     Critical: Elevates to call code that extracts
        ///               the deployment code base and is used to make trust decisions
        ///               Assuming we are accessing http content from an https site it will
        ///               throw a demand
        /// </SecurityNote>
        [SecurityCritical]
        internal static void BlockCrossDomainForHttpsApps(Uri uri)
        {
            // if app is HTTPS, no cross domain allowed
            Uri appDeploymentUri = ExtractUriForClickOnceDeployedApp();
            if (appDeploymentUri != null && appDeploymentUri.Scheme == Uri.UriSchemeHttps)
            {
                // demand
                if (uri.IsUnc || uri.IsFile)
                {
                    (new FileIOPermission(FileIOPermissionAccess.Read, uri.LocalPath)).Demand();
                }
                else
                {
                    (new WebPermission(NetworkAccess.Connect, BindUriHelper.UriToString(uri))).Demand();
                }
            }
        }
 
        // EnforceUncContentAccessRules implements UNC media & imaging access rules
        /// <SecurityNote>
        /// Critical - calls MapUrlToZoneWrapper.
        /// This is safe to be called by untrusted parties; all it does is demand permissions
        /// if a condition for accessing Unc content is not satisfied, but since we want to track
        /// its callers, we are not marking this as SecurityTreatAsSafe.
        /// </SecurityNote>
        [SecurityCritical]
        internal static void EnforceUncContentAccessRules(Uri contentUri)
        {
            // this should be called only for UNC content
            Invariant.Assert(contentUri.IsUnc);
 
            // get app zone and scheme
            Uri appUri = SecurityHelper.ExtractUriForClickOnceDeployedApp();
            if( appUri == null )
            {
                // we are not in a browser hosted app; we are not in partial trust, so don't block
                return;
            }
 
            // get app's zone
            int appZone = SecurityHelper.MapUrlToZoneWrapper(appUri);
 
            // demand if
            // 1) app comes from Internet or a more untrusted zone, or
            // 2) app comes from Intranet and scheme is HTTPS
            bool isInternetOrLessTrustedApp = (appZone >= MS.Win32.NativeMethods.URLZONE_INTERNET);
            bool isIntranetHttpsApp = (appZone == MS.Win32.NativeMethods.URLZONE_INTRANET && appUri.Scheme == Uri.UriSchemeHttps);
            if (isInternetOrLessTrustedApp || isIntranetHttpsApp)
            {
                // demand appropriate permission - we already know that contentUri is Unc
                (new FileIOPermission(FileIOPermissionAccess.Read, contentUri.LocalPath)).Demand();
            }
        }
 
         /// <SecurityNote>
         ///   Critical: This code elevates to call MapUrlToZone in the form of a SUC
         /// </SecurityNote>
         [SecurityCritical]
         internal static int MapUrlToZoneWrapper(Uri uri)
         {
              int targetZone = NativeMethods.URLZONE_LOCAL_MACHINE ; // fail securely this is the most priveleged zone
              int hr = NativeMethods.S_OK ;
              object curSecMgr = null;
              hr = UnsafeNativeMethods.CoInternetCreateSecurityManager(
                                                                       null,
                                                                       out curSecMgr ,
                                                                       0 );
              if ( NativeMethods.Failed( hr ))
                  throw new Win32Exception( hr ) ;
 
              UnsafeNativeMethods.IInternetSecurityManager pSec = (UnsafeNativeMethods.IInternetSecurityManager) curSecMgr;
 
              string uriString = BindUriHelper.UriToString( uri ) ;
              //
              // special case the condition if file is on local machine or UNC to ensure that content with mark of the web
              // does not yield with an internet zone result
              //
              if (uri.IsFile)
              {
                  pSec.MapUrlToZone( uriString, out targetZone, MS.Win32.NativeMethods.MUTZ_NOSAVEDFILECHECK );
              }
              else
              {
                  pSec.MapUrlToZone( uriString, out targetZone, 0 );
              }
              //
              // This is the condition for Invalid zone
              //
              if (targetZone < 0)
              {
                throw new SecurityException( SR.Get(SRID.Invalid_URI) );
              }
              pSec = null;
              curSecMgr = null;
              return targetZone;
        }
 
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandFilePathDiscoveryWriteRead()
        {
            FileIOPermission permobj = new FileIOPermission(PermissionState.None);
            permobj.AllFiles = FileIOPermissionAccess.Write|FileIOPermissionAccess.Read |FileIOPermissionAccess.PathDiscovery;
            permobj.Demand();
        }
 
        ///<SecurityNote>
        ///  Critical: This extracts permission set for app domain
        ///</SecurityNote>
        [SecurityCritical]
        internal static PermissionSet ExtractAppDomainPermissionSetMinusSiteOfOrigin()
        {
            PermissionSet permissionSetAppDomain = AppDomain.CurrentDomain.PermissionSet;
 
            // Ensure we remove the FileIO read permission to site of origin.
            // We choose to use unrestricted here because it does not matter
            // matter which specific variant of Fileio/Web permission we use
            // since we are using an overload to check and remove permission
            // that works on type. There is not a way to remove some
            // part of a permission, although we could remove this and add
            // back the delta if the existing permission set had more than the ones
            // we care about but it is really the path we are targeting here since
            // that is what causes the delta and hence we are removing it all together.
            Uri siteOfOrigin = SiteOfOriginContainer.SiteOfOrigin;
            CodeAccessPermission siteOfOriginReadPermission =  null;
            if (siteOfOrigin.Scheme == Uri.UriSchemeFile)
            {
                siteOfOriginReadPermission = new FileIOPermission(PermissionState.Unrestricted);
            }
            else if (siteOfOrigin.Scheme == Uri.UriSchemeHttp)
            {
                siteOfOriginReadPermission = new WebPermission(PermissionState.Unrestricted);
            }
 
            if (siteOfOriginReadPermission != null)
            {
                if (permissionSetAppDomain.GetPermission(siteOfOriginReadPermission.GetType()) != null)
                {
                    permissionSetAppDomain.RemovePermission(siteOfOriginReadPermission.GetType());
                    // Failing on a ReadOnlyPermissionSet here? See Dev10.697110.
                }
            }
            return permissionSetAppDomain;
        }
 
#endif
 
#if PRESENTATION_CORE
        /// <summary>
        /// determines if the current call stack has the serialization formatter
        /// permission. This is one of the few CLR checks that doesn't have a
        /// bool version - you have to let the check fail and catch the exception.
        ///
        /// Because this is a check *at that point*, you may not cache this value.
        /// </summary>
        /// <returns>true if call stack has the serialization permission</returns>
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// Safe     - The method denies the caller access to the full exception object.
        /// </SecurityNote>
        [SecuritySafeCritical]
        internal static bool CallerHasSerializationPermission()
        {
            try
            {
                if(_serializationSecurityPermission == null)
                {
                    _serializationSecurityPermission = new SecurityPermission(SecurityPermissionFlag.SerializationFormatter);
                }
                _serializationSecurityPermission.Demand();
            }
            catch (SecurityException)
            {
                return false;
            }
            return true;
        }
        static SecurityPermission _serializationSecurityPermission = null;
 
        /// <summary>
        /// determines if the current call stack has the all clipboard
        /// permission. This is one of the few CLR checks that doesn't have a
        /// bool version - you have to let the check fail and catch the exception.
        ///
        /// Because this is a check *at that point*, you may not cache this value.
        /// </summary>
        /// <returns>true if call stack has the all clipboard</returns>
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// Safe     - The method denies the caller access to the full exception object.
        /// </SecurityNote>
        [SecuritySafeCritical]
        internal static bool CallerHasAllClipboardPermission()
        {
            try
            {
                SecurityHelper.DemandAllClipboardPermission();
            }
            catch (SecurityException)
            {
                return false;
            }
            return true;
        }
 
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandAllClipboardPermission()
        {
            if(_uiPermissionAllClipboard == null)
            {
                _uiPermissionAllClipboard = new UIPermission(UIPermissionClipboard.AllClipboard);
            }
            _uiPermissionAllClipboard.Demand();
        }
        static UIPermission _uiPermissionAllClipboard = null;
 
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandPathDiscovery(string path)
        {
            new FileIOPermission(FileIOPermissionAccess.PathDiscovery, path).Demand();
        }
 
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// Safe     - The method denies the caller access to the full exception object.
        /// </SecurityNote>
        [SecuritySafeCritical]
        internal static bool CheckEnvironmentPermission()
        {
            try
            {
                SecurityHelper.DemandEnvironmentPermission();
            }
            catch (SecurityException)
            {
                return false ;
            }
 
            return true;
        }
 
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandEnvironmentPermission()
        {
            if(_unrestrictedEnvironmentPermission == null)
            {
                _unrestrictedEnvironmentPermission = new EnvironmentPermission(PermissionState.Unrestricted);
            }
            _unrestrictedEnvironmentPermission.Demand();
        }
        static EnvironmentPermission _unrestrictedEnvironmentPermission = null;
 
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandUriDiscoveryPermission(Uri uri)
        {
            CodeAccessPermission permission = CreateUriDiscoveryPermission(uri);
            if (permission != null)
                permission.Demand();
        }
 
        ///<SecurityNote>
        ///  Critical: Returns a permission object, which can be misused.
        ///</SecurityNote>
        [SecurityCritical]
        internal static CodeAccessPermission CreateUriDiscoveryPermission(Uri uri)
        {
            // explicitly disallow sub-classed Uris to guard against
            // exploits where we "lie" about some of the properties on the Uri.
            // and then later change the value returned
            //      ( e.g. supply a different uri from what checked here)
            if (uri.GetType().IsSubclassOf(typeof(Uri)))
            {
                DemandInfrastructurePermission();
            }
 
            if (uri.IsFile)
                return new FileIOPermission(FileIOPermissionAccess.PathDiscovery, uri.LocalPath);
 
            // Add appropriate demands for other Uri types here.
            return null;
        }
 
        ///<SecurityNote>
        ///  Critical: Returns a permission object, which can be misused.
        ///</SecurityNote>
        [SecurityCritical]
        internal static CodeAccessPermission CreateUriReadPermission(Uri uri)
        {
            // explicitly disallow sub-classed Uris to guard against
            // exploits where we "lie" about some of the properties on the Uri.
            // and then later change the value returned
            //      ( e.g. supply a different uri from what checked here)
            if (uri.GetType().IsSubclassOf(typeof(Uri)))
            {
                DemandInfrastructurePermission();
            }
 
            if (uri.IsFile)
                return new FileIOPermission(FileIOPermissionAccess.Read, uri.LocalPath);
 
            // Add appropriate demands for other Uri types here.
            return null;
        }
 
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandUriReadPermission(Uri uri)
        {
            CodeAccessPermission permission = CreateUriReadPermission(uri);
            if (permission != null)
                permission.Demand();
        }
 
        /// <summary>
        /// Checks whether the caller has path discovery permission for the input path.
        /// </summary>
        /// <param name="path">Full path to a file or a directory.</param>
        /// <returns>true if the caller has the discovery permission, false otherwise.</returns>
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// Safe     - The method denies the caller access to the full exception object.
        /// </SecurityNote>
        [SecuritySafeCritical]
        internal static bool CallerHasPathDiscoveryPermission(string path)
        {
            try
            {
                DemandPathDiscovery(path);
                return true;
            }
            catch (SecurityException)
            {
                return false;
            }
        }
 
        /// <summary>
        /// The permission set required to use encrypted package envelopes
        /// </summary>
        ///<SecurityNote>
        ///  Critical: Returns a permission object, which can be misused.
        ///</SecurityNote>
        internal static PermissionSet EnvelopePermissionSet
        {
            [SecurityCritical]
            get
            {
                if (_envelopePermissionSet == null)
                {
                    _envelopePermissionSet = CreateEnvelopePermissionSet();
                }
                return _envelopePermissionSet;
            }
        }
        private static PermissionSet _envelopePermissionSet = null;
 
        /// <summary>
        /// Creates a permission set that includes all permissions necessary to
        /// use EncryptedPackageEnvelope.
        /// </summary>
        /// <returns>The appropriate permission set</returns>
        ///<SecurityNote>
        ///  Critical: Returns a permission object, which can be misused.
        ///</SecurityNote>
        [SecurityCritical]
        private static PermissionSet CreateEnvelopePermissionSet()
        {
            PermissionSet permissionSet = new PermissionSet(PermissionState.None);
            permissionSet.AddPermission(new RightsManagementPermission());
            permissionSet.AddPermission(new CompoundFileIOPermission());
 
            return permissionSet;
        }
 
#endif
 
 
#if WINDOWS_BASE
        ///<SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        ///</SecurityNote>
        [SecurityCritical]
        internal static void DemandRightsManagementPermission()
        {
            if(_rightsManagementPermission == null)
            {
                _rightsManagementPermission = new RightsManagementPermission();
            }
            _rightsManagementPermission.Demand();
        }
        static RightsManagementPermission _rightsManagementPermission = null;
 
        ///<SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        ///</SecurityNote>
        [SecurityCritical]
        internal static void DemandCompoundFileIOPermission()
        {
            if(_compoundFileIOPermission == null)
            {
                _compoundFileIOPermission = new CompoundFileIOPermission();
            }
            _compoundFileIOPermission.Demand();
        }
        static CompoundFileIOPermission _compoundFileIOPermission = null;
 
        ///<SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        ///</SecurityNote>
        [SecurityCritical]
        internal static void DemandPathDiscovery(string path)
        {
            FileIOPermission permobj = new FileIOPermission(PermissionState.None);
            permobj.AddPathList(FileIOPermissionAccess.PathDiscovery, path);
            permobj.Demand();
        }
 
        /// <SecurityNote>
        /// SecurityCritical is needed due to Dev10 bug 534574. This is a TEMPORARY WORKAROUND for v4.
        /// TAS: Callers are transparent, so we need this too to keep them working.
        ///
        /// Note that the XAML reader relies on being able to call RunClassConstructor() on non-public types.
        /// This is considered a security flaw, and a future version of the CLR will likely plug it.
        /// </SecurityNote>
        [SecuritySafeCritical]
        internal static void RunClassConstructor(Type t)
        {
            System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(t.TypeHandle);
        }
 
#endif //  WINDOWS_BASE
 
#if DRT
        /// <SecurityNote>
        /// Critical: This calls into Marshal.SizeOf which has a link demand
        /// TreatAsSafe: Determining size is deemed as a safe operation
        /// </SecurityNote>
        /// <remarks> The LinkDemand on Marshal.SizeOf() was removed in v4. </remarks>
        [SecuritySafeCritical]
        internal static int SizeOf(Type t)
        {
            return Marshal.SizeOf(t);
        }
#endif
 
#if DRT
        /// <SecurityNote>
        /// Critical: This calls into Marshal.SizeOf which has a link demand
        /// TreatAsSafe: Determining size is deemed as a safe operation
        /// </SecurityNote>
        [SecuritySafeCritical]
        internal static int SizeOf(Object o)
        {
            return Marshal.SizeOf(o);
        }
#endif
 
#if WINDOWS_BASE || PRESENTATION_CORE || PRESENTATIONFRAMEWORK
        /// <SecurityNote>
        /// Critical: This calls into Marshal.GetExceptionForHR which is critical
        ///           it populates the exception object from data stored in a per thread IErrorInfo
        ///           the IErrorInfo may have security sensitive information like file paths stored in it
        /// TreatAsSafe: Uses overload of GetExceptionForHR that omits IErrorInfo information from exception message
        /// </SecurityNote>
        [SecuritySafeCritical]
        internal static Exception GetExceptionForHR(int hr)
        {
            return Marshal.GetExceptionForHR(hr, new IntPtr(-1));
        }
#endif
 
#if WINDOWS_BASE || PRESENTATION_CORE
        /// <SecurityNote>
        /// Critical: This calls into Marshal.ThrowExceptionForHR which is critical because 
        ///           it populates the exception object from data stored in a per thread IErrorInfo
        ///           the IErrorInfo may have security sensitive information like file paths stored in it
        /// TreatAsSafe: Uses overload of ThrowExceptionForHR that omits IErrorInfo information from exception message
        /// </SecurityNote>
        [SecuritySafeCritical]
        internal static void ThrowExceptionForHR(int hr)
        {
            Marshal.ThrowExceptionForHR(hr, new IntPtr(-1));
        }
        
        /// <SecurityNote>
        /// Critical: This calls into Marshal.GetHRForException which is critical
        ///           because it fills a per thread IErrorInfo with data in the Exception
        ///           the Exception may have security sensitive data like file paths stored in it
        /// TreatAsSafe: Clears the per thread IErrorInfo by calling GetHRForException a second time 
        ///              with an exception object with no security sensitive information
        /// </SecurityNote>
        [SecuritySafeCritical]
        internal static int GetHRForException(Exception exception)
        {
            if (exception == null)
            {
                throw new ArgumentNullException("exception");
            }
 
            // GetHRForException fills a per thread IErrorInfo object with data from the exception
            // The exception may contain security sensitive data like full file paths that we do not
            // want to leak into an IErrorInfo
            int hr = Marshal.GetHRForException(exception);
 
            // Call GetHRForException a second time with a security safe exception object
            // to make sure the per thread IErrorInfo is cleared of security sensitive data
            Marshal.GetHRForException(new Exception());
 
            return hr;
        }
 
#endif
 
#if PRESENTATION_CORE
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandRegistryPermission()
        {
            if(_unrestrictedRegistryPermission == null)
            {
                _unrestrictedRegistryPermission = new RegistryPermission(PermissionState.Unrestricted);
            }
            _unrestrictedRegistryPermission.Demand();
        }
        static RegistryPermission _unrestrictedRegistryPermission = null;
#endif // PRESENTATION_CORE
 
#if !PBTCOMPILER
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandUIWindowPermission()
        {
            if(_allWindowsUIPermission == null)
            {
                _allWindowsUIPermission = new UIPermission(UIPermissionWindow.AllWindows);
            }
            _allWindowsUIPermission.Demand();
        }
        static UIPermission _allWindowsUIPermission = null;
#endif
#if PRESENTATION_CORE
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandInfrastructurePermission()
        {
            if(_infrastructurePermission == null)
            {
                _infrastructurePermission = new SecurityPermission( SecurityPermissionFlag.Infrastructure );
            }
            _infrastructurePermission.Demand();
        }
        static SecurityPermission _infrastructurePermission = null;
 
#endif
 
#if PRESENTATION_CORE || REACHFRAMEWORK

        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandMediaPermission(MediaPermissionAudio audioPermissionToDemand,
                                                   MediaPermissionVideo videoPermissionToDemand,
                                                   MediaPermissionImage imagePermissionToDemand)
        {
            // Demand the appropriate permission
           (new MediaPermission(audioPermissionToDemand,
                                videoPermissionToDemand,
                                imagePermissionToDemand )).Demand();
        }
 
 
        ///<summary>
        /// Check whether the call stack has the permissions needed for safe media.
        ///
        /// </summary>
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// Safe     - The method denies the caller access to the full exception object.
        /// </SecurityNote>
#if REACHFRAMEWORK        
        [SecurityCritical]
#else        
        [SecuritySafeCritical]
#endif        
        internal static bool CallerHasMediaPermission(MediaPermissionAudio audioPermissionToDemand,
                                                      MediaPermissionVideo videoPermissionToDemand,
                                                      MediaPermissionImage imagePermissionToDemand)
        {
            try
            {
                (new MediaPermission(audioPermissionToDemand,videoPermissionToDemand,imagePermissionToDemand)).Demand();
                return true;
            }
            catch(SecurityException)
            {
                    return false;
            }
        }
#endif
 
 
 
        // don't include this in the compiler - avoid compiler changes when we can.
#if !PBTCOMPILER
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandUnrestrictedUIPermission()
        {
            if(_unrestrictedUIPermission == null)
            {
                _unrestrictedUIPermission = new UIPermission(PermissionState.Unrestricted);
            }
            _unrestrictedUIPermission.Demand();
        }
        static UIPermission _unrestrictedUIPermission = null;
#endif
 
#if PRESENTATION_CORE
        internal static bool AppDomainGrantedUnrestrictedUIPermission
        {
            [SecurityCritical]
            get
            {
                if(!_appDomainGrantedUnrestrictedUIPermission.HasValue)
                {
                    _appDomainGrantedUnrestrictedUIPermission = AppDomainHasPermission(new UIPermission(PermissionState.Unrestricted));
                }
 
                return _appDomainGrantedUnrestrictedUIPermission.Value;
            }
        }
        [SecurityCritical]
        private static bool? _appDomainGrantedUnrestrictedUIPermission;
 
#endif
 
#if PRESENTATION_CORE
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandFileIOReadPermission(string fileName)
        {
            new FileIOPermission(FileIOPermissionAccess.Read, fileName).Demand();
        }
#endif
 
#if NEVER
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandFileDialogSavePermission()
        {
            if(_fileDialogSavePermission == null)
            {
                _fileDialogSavePermission = new FileDialogPermission(FileDialogPermissionAccess.Save);
            }
            _fileDialogSavePermission.Demand();
        }
        static FileDialogPermission _fileDialogSavePermission = null;
#endif
 
#if PRESENTATIONFRAMEWORK
 
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandUnrestrictedFileIOPermission()
        {
            if(_unrestrictedFileIOPermission == null)
            {
                _unrestrictedFileIOPermission = new FileIOPermission(PermissionState.Unrestricted);
            }
            _unrestrictedFileIOPermission.Demand();
        }
        static FileIOPermission _unrestrictedFileIOPermission = null;
 
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandFileDialogOpenPermission()
        {
            if(_fileDialogOpenPermission == null)
            {
                _fileDialogOpenPermission = new FileDialogPermission(FileDialogPermissionAccess.Open);
            }
            _fileDialogOpenPermission.Demand();
        }
        static FileDialogPermission _fileDialogOpenPermission = null;
 
        /// <summary>
        /// A helper method to do the necessary work to display a standard MessageBox.  This method performs
        /// and necessary elevations to make the dialog work as well.
        /// </summary>
        /// <SecurityNote>
        ///     Critical - Elevates for unmanaged code permissions to display a messagebox (internally, it calls
        ///                MessageBox WIN32 API).
        ///     TreatAsSafe - The MessageBox API takes a static strings and known enums as input.  There is nothing
        ///                   unsafe with the dialog and it is not spoofable from Avalon as it is a Win32 window.
        /// </SecurityNote>
        [SecurityCritical, SecurityTreatAsSafe]
        internal
        static
        void
        ShowMessageBoxHelper(
            System.Windows.Window parent,
            string text,
            string title,
            System.Windows.MessageBoxButton buttons,
            System.Windows.MessageBoxImage image
            )
        {
            (new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)).Assert();
            try
            {
                // if we have a known parent window set, let's use it when alerting the user.
                if (parent != null)
                {
                    System.Windows.MessageBox.Show(parent, text, title, buttons, image);
                }
                else
                {
                    System.Windows.MessageBox.Show(text, title, buttons, image);
                }
            }
            finally
            {
                SecurityPermission.RevertAssert();
            }
        }
        /// <summary>
        /// A helper method to do the necessary work to display a standard MessageBox.  This method performs
        /// and necessary elevations to make the dialog work as well.
        /// </summary>
        /// <SecurityNote>
        ///     Critical - Elevates for unmanaged code permissions to display a messagebox (internally, it calls
        ///                MessageBox WIN32 API).
        ///     TreatAsSafe - The MessageBox API takes a static strings and known enums as input.  There is nothing
        ///                   unsafe with the dialog and it is not spoofable from Avalon as it is a Win32 window.
        /// </SecurityNote>
        [SecurityCritical, SecurityTreatAsSafe]
        internal
        static
        void
        ShowMessageBoxHelper(
            IntPtr parentHwnd,
            string text,
            string title,
            System.Windows.MessageBoxButton buttons,
            System.Windows.MessageBoxImage image
            )
        {
            (new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)).Assert();
            try
            {
                // NOTE: the last param must always be MessageBoxOptions.None for this to be considered TreatAsSafe
                System.Windows.MessageBox.ShowCore(parentHwnd, text, title, buttons, image, MessageBoxResult.None, MessageBoxOptions.None);
            }
            finally
            {
                SecurityPermission.RevertAssert();
            }
        }
#endif
 
 
#if PRESENTATION_CORE || REACHFRAMEWORK
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandMediaAccessPermission(String uri)
        {
            CodeAccessPermission casPermission= SecurityHelper.CreateMediaAccessPermission(uri);
            if(casPermission != null)
            {
                casPermission.Demand();
            }
        }
#endif
 
#if PRESENTATION_CORE || REACHFRAMEWORK
        ///<SecurityNote>
        ///  Critical: Returns a permission object, which can be misused.
        ///</SecurityNote>
        [SecurityCritical]
        internal
        static
        CodeAccessPermission
        CreateMediaAccessPermission(String uri)
        {
            CodeAccessPermission codeAccessPermission = null;
            if (uri != null)
            {
                // do a Case invariant dotnet culture specific string compare
                if (String.Compare(SafeSecurityHelper.IMAGE, uri, true/*Ignore case*/, TypeConverterHelper.InvariantEnglishUS ) == 0)
                {
                    codeAccessPermission = new MediaPermission(MediaPermissionAudio.NoAudio,
                                                               MediaPermissionVideo.NoVideo,
                                                               MediaPermissionImage.AllImage);
                }
                else
                {
                    // we allow access to pack: bits so assuming scheme is not pack: we demand
                    if (String.Compare((System.Windows.Navigation.BaseUriHelper.GetResolvedUri(System.Windows.Navigation.BaseUriHelper.BaseUri, new Uri(uri, UriKind.RelativeOrAbsolute))).Scheme,
                                       PackUriHelper.UriSchemePack, true /* ignore case */,
                                       TypeConverterHelper.InvariantEnglishUS) != 0)
                    {
                        // Creating a URI is fine it is going the other way that is risky
                        if(!SecurityHelper.CallerHasWebPermission(new Uri(uri,UriKind.RelativeOrAbsolute)))
                        {
                            codeAccessPermission = new MediaPermission(MediaPermissionAudio.NoAudio,
                                                                       MediaPermissionVideo.NoVideo,
                                                                       MediaPermissionImage.AllImage);
                        }
 
                    }
                }
            }
            else
            {
                codeAccessPermission = new MediaPermission(MediaPermissionAudio.NoAudio,
                                                           MediaPermissionVideo.NoVideo,
                                                           MediaPermissionImage.AllImage);
            }
            return codeAccessPermission;
        }
 
        ///<summary>
        ///   Check caller has web-permission. for a given Uri.
        /// </summary>
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// Safe     - The method denies the caller access to the full exception object.
        /// </SecurityNote>
#if REACHFRAMEWORK        
        [SecurityCritical]
#else        
        [SecuritySafeCritical]
#endif        
        internal static bool CallerHasWebPermission( Uri uri )
        {
            try
            {
                SecurityHelper.DemandWebPermission(uri);
                return true;
            }
            catch ( SecurityException )
            {
                return false ;
            }
        }
 
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        [SecurityCritical]
        internal static void DemandWebPermission( Uri uri )
        {
            // We do this first as a security measure since the call below
            // checks for derivatives. Please note we need to extract the
            // string to call into WebPermission anyways, the only thing that
            // doing this early gains us is a defense in depth measure. The call
            // is required nevertheless.
            string finalUri = BindUriHelper.UriToString( uri );
 
            if (uri.IsFile)
            {
                // If the scheme is file: demand file io
                string toOpen = uri.LocalPath;
                (new FileIOPermission(FileIOPermissionAccess.Read, toOpen)).Demand();
            }
            else
            {
                // else demand web permissions
                new WebPermission(NetworkAccess.Connect, finalUri).Demand();
            }
        }
 
#endif //PRESENTATIONCORE||REACHFRAMEWORK
 
#if PRESENTATION_CORE || PRESENTATIONFRAMEWORK || REACHFRAMEWORK
        /// <SecurityNote>
        /// Critical - Exceptions raised by a demand may contain security sensitive information that should not be passed to transparent callers
        /// </SecurityNote>
        /// <summary>
        /// By default none of the plug-in serializer code must succeed for partially trusted callers
        /// </summary>
        [SecurityCritical]
        internal static void DemandPlugInSerializerPermissions()
        {
            if(_plugInSerializerPermissions == null)
            {
                _plugInSerializerPermissions = new PermissionSet(PermissionState.Unrestricted);
            }
            _plugInSerializerPermissions.Demand();
        }
        static PermissionSet _plugInSerializerPermissions = null;
#endif //PRESENTATIONFRAMEWORK
 
#if PRESENTATION_CORE || PRESENTATIONFRAMEWORK || WINDOWS_BASE
 
        /// <SecurityNote>
        /// This method has security implications: Mime\ContentTypes\Uri schemes types are served in a case-insensitive fashion; they MUST be compared that way
        /// </SecurityNote>
        internal static bool AreStringTypesEqual(string m1, string m2)
        {
            return (String.Compare(m1, m2, StringComparison.OrdinalIgnoreCase) == 0);
        }
 
#endif //PRESENTATION_CORE || PRESENTATIONFRAMEWORK || WINDOWS_BASE
 
 
#if WINDOWS_BASE
        ///
        /// Read and return a registry value.
        ///<SecurityNote>
        /// Critical - Asserts registry permission on the caller-provided key.
        ///</SecurityNote>
       [SecurityCritical]
       static internal object ReadRegistryValue( RegistryKey baseRegistryKey, string keyName, string valueName )
       {
            object value = null;
 
            new RegistryPermission(RegistryPermissionAccess.Read, baseRegistryKey.Name + @"\" + keyName).Assert();
            try
            {
                RegistryKey key = baseRegistryKey.OpenSubKey(keyName);
                if (key != null)
                {
                    using( key )
                    {
                        value = key.GetValue(valueName);
                    }
                }
            }
            finally
            {
                RegistryPermission.RevertAssert();
            }
 
            return value;
 
        }
#endif // WINDOWS_BASE
 
 
}
}