FontSource.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / MS / Internal / FontCache / FontSource.cs / 1305600 / FontSource.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// Description: The FontSource class. 
//
// History: 
//  08/04/2003 : mleonov - Created it 
//
//--------------------------------------------------------------------------- 

using System;
using System.Collections;
using System.ComponentModel; 
using System.Diagnostics;
using System.Globalization; 
using System.IO; 
using System.IO.Packaging;
using System.Net; 
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Windows; 
using System.Windows.Media;
using System.Windows.Threading; 
 
using MS.Win32;
using MS.Utility; 
using MS.Internal;
using MS.Internal.IO.Packaging;
using MS.Internal.PresentationCore;
using MS.Internal.Text.TextInterface; 

namespace MS.Internal.FontCache 
{ 
    internal class FontSourceFactory : IFontSourceFactory
    { 
        public FontSourceFactory() { }

        /// 
        ///     Critical - retreives security sensitive info about a FontSource like raw font data. 
        ///     Safe     - does a demand before it gives out the information asked.
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        public IFontSource Create(string uriString)
        { 
            return new FontSource(new Uri(uriString), false);
        }
    }
 
    /// 
    /// FontSource class encapsulates the logic for dealing with fonts in memory or on the disk. 
    /// It may or may not have a Uri associated with it, but there has to be some way to obtain its contents. 
    /// 
    internal class FontSource : IFontSource 
    {
        //-----------------------------------------------------
        //
        //  Constructors 
        //
        //----------------------------------------------------- 
 
        #region Constructors
 
        /// 
        /// Critical - Calls Security Critical method Initialize().
        /// 
        [SecurityCritical] 
        public FontSource(Uri fontUri, bool skipDemand)
        { 
            Initialize(fontUri, skipDemand, false); 
        }
 
        /// 
        /// Critical - Calls Security Critical method Initialize().
        /// 
        [SecurityCritical] 
        public FontSource(Uri fontUri, bool skipDemand, bool isComposite)
        { 
            Initialize(fontUri, skipDemand, isComposite); 
        }
 
        /// 
        /// Critical - fontUri can contain information about local file system, skipDemand is used to make security decisions.
        /// 
        [SecurityCritical] 
        private void Initialize(Uri fontUri, bool skipDemand, bool isComposite)
        { 
            _fontUri = fontUri; 
            _skipDemand = skipDemand;
            _isComposite = isComposite; 
            Invariant.Assert(_fontUri.IsAbsoluteUri);
            Debug.Assert(String.IsNullOrEmpty(_fontUri.Fragment));
        }
 
        #endregion Constructors
 
        //------------------------------------------------------ 
        //
        //  Internal Methods 
        //
        //-----------------------------------------------------

        #region Internal Methods 

        public bool IsComposite 
        { 
            get
            { 
                return _isComposite;
            }
        }
 
        /// 
        /// Critical - as this gives out full file path. 
        ///  
        [SecurityCritical]
        public string GetUriString() 
        {
            return _fontUri.GetComponents(UriComponents.AbsoluteUri, UriFormat.SafeUnescaped);
        }
 
        /// 
        /// Critical - as this gives out full file path. 
        ///  
        [SecurityCritical]
        public string ToStringUpperInvariant() 
        {
            return GetUriString().ToUpperInvariant();
        }
 
        /// 
        /// Critical - fontUri can contain information about local file system. 
        /// TreatAsSafe - we only compute its hash code. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        public override int GetHashCode()
        {
            return HashFn.HashString(ToStringUpperInvariant(), 0);
        } 

 
        ///  
        /// Critical - as this gives out full file path.
        ///  
        public Uri Uri
        {
            [SecurityCritical]
            get 
            {
                return _fontUri; 
            } 
        }
 
        /// 
        /// Critical - fontUri can contain information about local file system.
        /// TreatAsSafe - we only return a flag that says whether the Uri is app specific.
        ///  
        public bool IsAppSpecific
        { 
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            { 
                return Util.IsAppSpecificUri(_fontUri);
            }
        }
 
        internal long SkipLastWriteTime()
        { 
            // clients may choose to use this temporary method because GetLastWriteTime call 
            // results in touching the file system
            // we need to resurrect this code when we come up with a complete solution 
            // for updating fonts on the fly
            return -1; // any non-zero value will do here
        }
 
        /// 
        /// Critical - elevates to obtain the last write time for %windir%\fonts. 
        /// Also, fontUri can contain information about local file system. 
        /// TreatAsSafe - we only use it to obtain the last write time.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        public DateTime GetLastWriteTimeUtc()
        {
            if (_fontUri.IsFile) 
            {
                bool revertAssert = false; 
 
                // Assert FileIORead permission for installed fonts.
                if (_skipDemand) 
                {
                    new FileIOPermission(FileIOPermissionAccess.Read, _fontUri.LocalPath).Assert(); //Blessed Assert
                    revertAssert = true;
                } 

                try 
                { 
                    return Directory.GetLastWriteTimeUtc(_fontUri.LocalPath);
                } 
                finally
                {
                    if (revertAssert)
                        CodeAccessPermission.RevertAssert(); 
                }
            } 
 
            // Any special value will do here.
            return DateTime.MaxValue; 
        }

        /// 
        /// Critical - as this gives out UnmanagedMemoryStream content which is from a file. 
        /// 
        [SecurityCritical] 
        public UnmanagedMemoryStream GetUnmanagedStream() 
        {
            if (_fontUri.IsFile) 
            {
                FileMapping fileMapping = new FileMapping();

                DemandFileIOPermission(); 

                fileMapping.OpenFile(_fontUri.LocalPath); 
                return fileMapping; 
            }
 
            byte[] bits;
            // Try our cache first.
            lock (_resourceCache)
            { 
                bits = _resourceCache.Get(_fontUri);
            } 
 
            if (bits == null)
            { 
                WebResponse response = WpfWebRequestHelper.CreateRequestAndGetResponse(_fontUri);
                Stream fontStream = response.GetResponseStream();
                if (String.Equals(response.ContentType, ObfuscatedContentType, StringComparison.Ordinal))
                { 
                    // The third parameter makes sure the original stream is closed
                    // when the deobfuscating stream is disposed. 
                    fontStream = new DeobfuscatingStream(fontStream, _fontUri, false); 
                }
 
                UnmanagedMemoryStream unmanagedStream = fontStream as UnmanagedMemoryStream;
                if (unmanagedStream != null)
                    return unmanagedStream;
 
                bits = StreamToByteArray(fontStream);
 
                fontStream.Close(); 

                lock (_resourceCache) 
                {
                    _resourceCache.Add(_fontUri, bits, false);
                }
            } 
            return ByteArrayToUnmanagedStream(bits);
        } 
 
        /// 
        /// Tries to open a file and throws exceptions in case of failures. This 
        /// method is used to achieve the same exception throwing behavior after
        /// integrating DWrite.
        /// 
        ///  
        /// Critical    - accesses security critical method FileMapping.OpenFile
        /// TreatAsSafe - Does not give out sensitive info. 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        public void TestFileOpenable() 
        {
            if (_fontUri.IsFile)
            {
                FileMapping fileMapping = new FileMapping(); 

                DemandFileIOPermission(); 
 
                fileMapping.OpenFile(_fontUri.LocalPath);
                fileMapping.Close(); 
            }
        }

        ///  
        /// Critical - as this gives out Stream content which is from a file.
        ///  
        [SecurityCritical] 
        public Stream GetStream()
        { 
            if (_fontUri.IsFile)
            {
                FileMapping fileMapping = new FileMapping();
 
                DemandFileIOPermission();
 
                fileMapping.OpenFile(_fontUri.LocalPath); 
                return fileMapping;
            } 

            byte[] bits;

            // Try our cache first. 
            lock (_resourceCache)
            { 
                bits = _resourceCache.Get(_fontUri); 
            }
 
            if (bits != null)
                return new MemoryStream(bits);

            WebRequest request = PackWebRequestFactory.CreateWebRequest(_fontUri); 
            WebResponse response = request.GetResponse();
 
            Stream fontStream = response.GetResponseStream(); 
            if (String.Equals(response.ContentType, ObfuscatedContentType, StringComparison.Ordinal))
            { 
                // The third parameter makes sure the original stream is closed
                // when the deobfuscating stream is disposed.
                fontStream = new DeobfuscatingStream(fontStream, _fontUri, false);
            } 
            return fontStream;
        } 
 
        #endregion Internal Methods
 
        //------------------------------------------------------
        //
        //  Private Methods
        // 
        //------------------------------------------------------
 
        #region Private Methods 

        private static UnmanagedMemoryStream ByteArrayToUnmanagedStream(byte[] bits) 
        {
            return new PinnedByteArrayStream(bits);
        }
 
        private static byte [] StreamToByteArray(Stream fontStream)
        { 
            byte[] memoryFont; 

            if (fontStream.CanSeek) 
            {
                checked
                {
                    memoryFont = new byte[(int)fontStream.Length]; 
                    PackagingUtilities.ReliableRead(fontStream, memoryFont, 0, (int)fontStream.Length);
                } 
            } 
            else
            { 
                // this is inefficient, but works for now
                // we need to spend more time to implement a more performant
                // version of this code
                // ideally this should be a part of loader functionality 

                // Initial file read buffer size is set to 1MB. 
                int fileReadBufferSize = 1024 * 1024; 
                byte[] fileReadBuffer = new byte[fileReadBufferSize];
 
                // Actual number of bytes read from the file.
                int memoryFontSize = 0;

                for (; ; ) 
                {
                    int availableBytes = fileReadBufferSize - memoryFontSize; 
                    if (availableBytes < fileReadBufferSize / 3) 
                    {
                        // grow the fileReadBuffer 
                        fileReadBufferSize *= 2;
                        byte[] newBuffer = new byte[fileReadBufferSize];
                        Array.Copy(fileReadBuffer, newBuffer, memoryFontSize);
                        fileReadBuffer = newBuffer; 
                        availableBytes = fileReadBufferSize - memoryFontSize;
                    } 
                    int numberOfBytesRead = fontStream.Read(fileReadBuffer, memoryFontSize, availableBytes); 
                    if (numberOfBytesRead == 0)
                        break; 

                    memoryFontSize += numberOfBytesRead;
                }
 
                // Actual number of bytes read from the file is less or equal to the file read buffer size.
                Debug.Assert(memoryFontSize <= fileReadBufferSize); 
 
                if (memoryFontSize == fileReadBufferSize)
                    memoryFont = fileReadBuffer; 
                else
                {
                    // Trim the array if needed to that it contains the right length.
                    memoryFont = new byte[memoryFontSize]; 
                    Array.Copy(fileReadBuffer, memoryFont, memoryFontSize);
                } 
            } 

            return memoryFont; 
        }

        /// 
        /// Demand read permissions for all fonts except system ones. 
        /// 
        ///  
        ///     Critical - as this function calls critical WindowsFontsUriObject. 
        ///     TreatAsSafe - as the WindowsFontsUriObject is used to determine whether to demand permissions.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private void DemandFileIOPermission()
        {
            // Demand FileIORead permission for any non-system fonts. 
            if (!_skipDemand)
            { 
                SecurityHelper.DemandUriReadPermission(_fontUri); 
            }
        } 

        #endregion Private Methods

        //----------------------------------------------------- 
        //
        //  Private Classes 
        // 
        //------------------------------------------------------
 
        #region Private Classes

        private class PinnedByteArrayStream : UnmanagedMemoryStream
        { 
            /// 
            ///     Critical - as this function calls GCHandle.Alloc and UnmanagedMemoryStream.Initialize methods 
            ///         which cause an elevation. 
            ///     TreatAsSafe - as this only pins and unpins an array of bytes.
            ///  
            [SecurityCritical, SecurityTreatAsSafe]
            internal PinnedByteArrayStream(byte [] bits)
            {
                _memoryHandle = GCHandle.Alloc(bits, GCHandleType.Pinned); 

                unsafe 
                { 
                    // Initialize() method demands UnmanagedCode permission, and PinnedByteArrayStream is already marked as critical.
 
                    new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); //Blessed Assert

                    try
                    { 
                        Initialize(
 	                        (byte *)_memoryHandle.AddrOfPinnedObject(), 
	                        bits.Length, 
	                        bits.Length,
	                        FileAccess.Read 
                        );
                    }
                    finally
                    { 
                        SecurityPermission.RevertAssert();
                    } 
                } 
            }
 
            ~PinnedByteArrayStream()
            {
                Dispose(false);
            } 

            ///  
            ///     Critical: This code calls into GCHandle.Free which is link demanded 
            ///     TreatAsSafe: This code is ok to call. In the worst case it destroys some
            ///     objects in the app 
            /// 
            [SecurityCritical,SecurityTreatAsSafe]
            protected override void Dispose(bool disposing)
            { 
                base.Dispose(disposing);
 
                Debug.Assert(_memoryHandle.IsAllocated); 
                _memoryHandle.Free();
            } 

            private GCHandle    _memoryHandle;
        }
 
        #endregion Private Classes
 
        //----------------------------------------------------- 
        //
        //  Private Fields 
        //
        //-----------------------------------------------------

        #region Private Fields 

        private bool _isComposite; 
 
        /// 
        /// Critical - fontUri can contain information about local file system. 
        /// 
        [SecurityCritical]
        private Uri     _fontUri;
 
        /// 
        /// Critical - determines whether the font source was constructed from internal data, 
        /// in which case the permission demand should be skipped. 
        /// 
        [SecurityCritical] 
        private bool    _skipDemand;

        private static SizeLimitedCache _resourceCache = new SizeLimitedCache(MaximumCacheItems);
 
        /// 
        /// The maximum number of fonts downloaded from pack:// Uris. 
        ///  
        private const int MaximumCacheItems = 10;
        private const string ObfuscatedContentType = "application/vnd.ms-package.obfuscated-opentype"; 

        #endregion Private Fields
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------------- 
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// Description: The FontSource class. 
//
// History: 
//  08/04/2003 : mleonov - Created it 
//
//--------------------------------------------------------------------------- 

using System;
using System.Collections;
using System.ComponentModel; 
using System.Diagnostics;
using System.Globalization; 
using System.IO; 
using System.IO.Packaging;
using System.Net; 
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Windows; 
using System.Windows.Media;
using System.Windows.Threading; 
 
using MS.Win32;
using MS.Utility; 
using MS.Internal;
using MS.Internal.IO.Packaging;
using MS.Internal.PresentationCore;
using MS.Internal.Text.TextInterface; 

namespace MS.Internal.FontCache 
{ 
    internal class FontSourceFactory : IFontSourceFactory
    { 
        public FontSourceFactory() { }

        /// 
        ///     Critical - retreives security sensitive info about a FontSource like raw font data. 
        ///     Safe     - does a demand before it gives out the information asked.
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        public IFontSource Create(string uriString)
        { 
            return new FontSource(new Uri(uriString), false);
        }
    }
 
    /// 
    /// FontSource class encapsulates the logic for dealing with fonts in memory or on the disk. 
    /// It may or may not have a Uri associated with it, but there has to be some way to obtain its contents. 
    /// 
    internal class FontSource : IFontSource 
    {
        //-----------------------------------------------------
        //
        //  Constructors 
        //
        //----------------------------------------------------- 
 
        #region Constructors
 
        /// 
        /// Critical - Calls Security Critical method Initialize().
        /// 
        [SecurityCritical] 
        public FontSource(Uri fontUri, bool skipDemand)
        { 
            Initialize(fontUri, skipDemand, false); 
        }
 
        /// 
        /// Critical - Calls Security Critical method Initialize().
        /// 
        [SecurityCritical] 
        public FontSource(Uri fontUri, bool skipDemand, bool isComposite)
        { 
            Initialize(fontUri, skipDemand, isComposite); 
        }
 
        /// 
        /// Critical - fontUri can contain information about local file system, skipDemand is used to make security decisions.
        /// 
        [SecurityCritical] 
        private void Initialize(Uri fontUri, bool skipDemand, bool isComposite)
        { 
            _fontUri = fontUri; 
            _skipDemand = skipDemand;
            _isComposite = isComposite; 
            Invariant.Assert(_fontUri.IsAbsoluteUri);
            Debug.Assert(String.IsNullOrEmpty(_fontUri.Fragment));
        }
 
        #endregion Constructors
 
        //------------------------------------------------------ 
        //
        //  Internal Methods 
        //
        //-----------------------------------------------------

        #region Internal Methods 

        public bool IsComposite 
        { 
            get
            { 
                return _isComposite;
            }
        }
 
        /// 
        /// Critical - as this gives out full file path. 
        ///  
        [SecurityCritical]
        public string GetUriString() 
        {
            return _fontUri.GetComponents(UriComponents.AbsoluteUri, UriFormat.SafeUnescaped);
        }
 
        /// 
        /// Critical - as this gives out full file path. 
        ///  
        [SecurityCritical]
        public string ToStringUpperInvariant() 
        {
            return GetUriString().ToUpperInvariant();
        }
 
        /// 
        /// Critical - fontUri can contain information about local file system. 
        /// TreatAsSafe - we only compute its hash code. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        public override int GetHashCode()
        {
            return HashFn.HashString(ToStringUpperInvariant(), 0);
        } 

 
        ///  
        /// Critical - as this gives out full file path.
        ///  
        public Uri Uri
        {
            [SecurityCritical]
            get 
            {
                return _fontUri; 
            } 
        }
 
        /// 
        /// Critical - fontUri can contain information about local file system.
        /// TreatAsSafe - we only return a flag that says whether the Uri is app specific.
        ///  
        public bool IsAppSpecific
        { 
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            { 
                return Util.IsAppSpecificUri(_fontUri);
            }
        }
 
        internal long SkipLastWriteTime()
        { 
            // clients may choose to use this temporary method because GetLastWriteTime call 
            // results in touching the file system
            // we need to resurrect this code when we come up with a complete solution 
            // for updating fonts on the fly
            return -1; // any non-zero value will do here
        }
 
        /// 
        /// Critical - elevates to obtain the last write time for %windir%\fonts. 
        /// Also, fontUri can contain information about local file system. 
        /// TreatAsSafe - we only use it to obtain the last write time.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        public DateTime GetLastWriteTimeUtc()
        {
            if (_fontUri.IsFile) 
            {
                bool revertAssert = false; 
 
                // Assert FileIORead permission for installed fonts.
                if (_skipDemand) 
                {
                    new FileIOPermission(FileIOPermissionAccess.Read, _fontUri.LocalPath).Assert(); //Blessed Assert
                    revertAssert = true;
                } 

                try 
                { 
                    return Directory.GetLastWriteTimeUtc(_fontUri.LocalPath);
                } 
                finally
                {
                    if (revertAssert)
                        CodeAccessPermission.RevertAssert(); 
                }
            } 
 
            // Any special value will do here.
            return DateTime.MaxValue; 
        }

        /// 
        /// Critical - as this gives out UnmanagedMemoryStream content which is from a file. 
        /// 
        [SecurityCritical] 
        public UnmanagedMemoryStream GetUnmanagedStream() 
        {
            if (_fontUri.IsFile) 
            {
                FileMapping fileMapping = new FileMapping();

                DemandFileIOPermission(); 

                fileMapping.OpenFile(_fontUri.LocalPath); 
                return fileMapping; 
            }
 
            byte[] bits;
            // Try our cache first.
            lock (_resourceCache)
            { 
                bits = _resourceCache.Get(_fontUri);
            } 
 
            if (bits == null)
            { 
                WebResponse response = WpfWebRequestHelper.CreateRequestAndGetResponse(_fontUri);
                Stream fontStream = response.GetResponseStream();
                if (String.Equals(response.ContentType, ObfuscatedContentType, StringComparison.Ordinal))
                { 
                    // The third parameter makes sure the original stream is closed
                    // when the deobfuscating stream is disposed. 
                    fontStream = new DeobfuscatingStream(fontStream, _fontUri, false); 
                }
 
                UnmanagedMemoryStream unmanagedStream = fontStream as UnmanagedMemoryStream;
                if (unmanagedStream != null)
                    return unmanagedStream;
 
                bits = StreamToByteArray(fontStream);
 
                fontStream.Close(); 

                lock (_resourceCache) 
                {
                    _resourceCache.Add(_fontUri, bits, false);
                }
            } 
            return ByteArrayToUnmanagedStream(bits);
        } 
 
        /// 
        /// Tries to open a file and throws exceptions in case of failures. This 
        /// method is used to achieve the same exception throwing behavior after
        /// integrating DWrite.
        /// 
        ///  
        /// Critical    - accesses security critical method FileMapping.OpenFile
        /// TreatAsSafe - Does not give out sensitive info. 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        public void TestFileOpenable() 
        {
            if (_fontUri.IsFile)
            {
                FileMapping fileMapping = new FileMapping(); 

                DemandFileIOPermission(); 
 
                fileMapping.OpenFile(_fontUri.LocalPath);
                fileMapping.Close(); 
            }
        }

        ///  
        /// Critical - as this gives out Stream content which is from a file.
        ///  
        [SecurityCritical] 
        public Stream GetStream()
        { 
            if (_fontUri.IsFile)
            {
                FileMapping fileMapping = new FileMapping();
 
                DemandFileIOPermission();
 
                fileMapping.OpenFile(_fontUri.LocalPath); 
                return fileMapping;
            } 

            byte[] bits;

            // Try our cache first. 
            lock (_resourceCache)
            { 
                bits = _resourceCache.Get(_fontUri); 
            }
 
            if (bits != null)
                return new MemoryStream(bits);

            WebRequest request = PackWebRequestFactory.CreateWebRequest(_fontUri); 
            WebResponse response = request.GetResponse();
 
            Stream fontStream = response.GetResponseStream(); 
            if (String.Equals(response.ContentType, ObfuscatedContentType, StringComparison.Ordinal))
            { 
                // The third parameter makes sure the original stream is closed
                // when the deobfuscating stream is disposed.
                fontStream = new DeobfuscatingStream(fontStream, _fontUri, false);
            } 
            return fontStream;
        } 
 
        #endregion Internal Methods
 
        //------------------------------------------------------
        //
        //  Private Methods
        // 
        //------------------------------------------------------
 
        #region Private Methods 

        private static UnmanagedMemoryStream ByteArrayToUnmanagedStream(byte[] bits) 
        {
            return new PinnedByteArrayStream(bits);
        }
 
        private static byte [] StreamToByteArray(Stream fontStream)
        { 
            byte[] memoryFont; 

            if (fontStream.CanSeek) 
            {
                checked
                {
                    memoryFont = new byte[(int)fontStream.Length]; 
                    PackagingUtilities.ReliableRead(fontStream, memoryFont, 0, (int)fontStream.Length);
                } 
            } 
            else
            { 
                // this is inefficient, but works for now
                // we need to spend more time to implement a more performant
                // version of this code
                // ideally this should be a part of loader functionality 

                // Initial file read buffer size is set to 1MB. 
                int fileReadBufferSize = 1024 * 1024; 
                byte[] fileReadBuffer = new byte[fileReadBufferSize];
 
                // Actual number of bytes read from the file.
                int memoryFontSize = 0;

                for (; ; ) 
                {
                    int availableBytes = fileReadBufferSize - memoryFontSize; 
                    if (availableBytes < fileReadBufferSize / 3) 
                    {
                        // grow the fileReadBuffer 
                        fileReadBufferSize *= 2;
                        byte[] newBuffer = new byte[fileReadBufferSize];
                        Array.Copy(fileReadBuffer, newBuffer, memoryFontSize);
                        fileReadBuffer = newBuffer; 
                        availableBytes = fileReadBufferSize - memoryFontSize;
                    } 
                    int numberOfBytesRead = fontStream.Read(fileReadBuffer, memoryFontSize, availableBytes); 
                    if (numberOfBytesRead == 0)
                        break; 

                    memoryFontSize += numberOfBytesRead;
                }
 
                // Actual number of bytes read from the file is less or equal to the file read buffer size.
                Debug.Assert(memoryFontSize <= fileReadBufferSize); 
 
                if (memoryFontSize == fileReadBufferSize)
                    memoryFont = fileReadBuffer; 
                else
                {
                    // Trim the array if needed to that it contains the right length.
                    memoryFont = new byte[memoryFontSize]; 
                    Array.Copy(fileReadBuffer, memoryFont, memoryFontSize);
                } 
            } 

            return memoryFont; 
        }

        /// 
        /// Demand read permissions for all fonts except system ones. 
        /// 
        ///  
        ///     Critical - as this function calls critical WindowsFontsUriObject. 
        ///     TreatAsSafe - as the WindowsFontsUriObject is used to determine whether to demand permissions.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private void DemandFileIOPermission()
        {
            // Demand FileIORead permission for any non-system fonts. 
            if (!_skipDemand)
            { 
                SecurityHelper.DemandUriReadPermission(_fontUri); 
            }
        } 

        #endregion Private Methods

        //----------------------------------------------------- 
        //
        //  Private Classes 
        // 
        //------------------------------------------------------
 
        #region Private Classes

        private class PinnedByteArrayStream : UnmanagedMemoryStream
        { 
            /// 
            ///     Critical - as this function calls GCHandle.Alloc and UnmanagedMemoryStream.Initialize methods 
            ///         which cause an elevation. 
            ///     TreatAsSafe - as this only pins and unpins an array of bytes.
            ///  
            [SecurityCritical, SecurityTreatAsSafe]
            internal PinnedByteArrayStream(byte [] bits)
            {
                _memoryHandle = GCHandle.Alloc(bits, GCHandleType.Pinned); 

                unsafe 
                { 
                    // Initialize() method demands UnmanagedCode permission, and PinnedByteArrayStream is already marked as critical.
 
                    new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); //Blessed Assert

                    try
                    { 
                        Initialize(
 	                        (byte *)_memoryHandle.AddrOfPinnedObject(), 
	                        bits.Length, 
	                        bits.Length,
	                        FileAccess.Read 
                        );
                    }
                    finally
                    { 
                        SecurityPermission.RevertAssert();
                    } 
                } 
            }
 
            ~PinnedByteArrayStream()
            {
                Dispose(false);
            } 

            ///  
            ///     Critical: This code calls into GCHandle.Free which is link demanded 
            ///     TreatAsSafe: This code is ok to call. In the worst case it destroys some
            ///     objects in the app 
            /// 
            [SecurityCritical,SecurityTreatAsSafe]
            protected override void Dispose(bool disposing)
            { 
                base.Dispose(disposing);
 
                Debug.Assert(_memoryHandle.IsAllocated); 
                _memoryHandle.Free();
            } 

            private GCHandle    _memoryHandle;
        }
 
        #endregion Private Classes
 
        //----------------------------------------------------- 
        //
        //  Private Fields 
        //
        //-----------------------------------------------------

        #region Private Fields 

        private bool _isComposite; 
 
        /// 
        /// Critical - fontUri can contain information about local file system. 
        /// 
        [SecurityCritical]
        private Uri     _fontUri;
 
        /// 
        /// Critical - determines whether the font source was constructed from internal data, 
        /// in which case the permission demand should be skipped. 
        /// 
        [SecurityCritical] 
        private bool    _skipDemand;

        private static SizeLimitedCache _resourceCache = new SizeLimitedCache(MaximumCacheItems);
 
        /// 
        /// The maximum number of fonts downloaded from pack:// Uris. 
        ///  
        private const int MaximumCacheItems = 10;
        private const string ObfuscatedContentType = "application/vnd.ms-package.obfuscated-opentype"; 

        #endregion Private Fields
    }
} 

// 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