ColorContext.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Core / CSharp / System / Windows / Media / ColorContext.cs / 1 / ColorContext.cs

                            //------------------------------------------------------------------------------ 
//  Microsoft Windows Client Platform
//  Copyright (c) Microsoft Corporation, All Rights Reserved.
//
//  File: ColorContext.cs 
//-----------------------------------------------------------------------------
#pragma warning disable 1634, 1691 // Allow suppression of certain presharp messages 
 
using System;
using MS.Internal; 
using MS.Internal.PresentationCore;
using MS.Win32;
using System.IO;
using System.Runtime.InteropServices; 
using System.Windows.Media;
using System.Resources; 
using System.Security; 
using System.Security.Permissions;
using System.Collections; 
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Reflection;
using System.Diagnostics; 
using System.Globalization;
using Microsoft.Win32.SafeHandles; 
using System.Net; 
using System.IO.Packaging;
using System.Windows.Navigation; 
using System.Diagnostics.CodeAnalysis;
using System.Text;

using SR=MS.Internal.PresentationCore.SR; 
using SRID=MS.Internal.PresentationCore.SRID;
using UnsafeNativeMethods=MS.Win32.PresentationCore.UnsafeNativeMethods; 
 
namespace System.Windows.Media
{ 
    /// 
    /// Color Context
    /// 
    public class ColorContext 
    {
 
        #region Constructors 

        ///  
        /// Don't allow construction of ColorContext with no params.
        /// 
        private ColorContext()
        { 
            _profileHeader.phSize = 0;               // profile size in bytes
            _profileHeader.phCMMType = 0;            // CMM for this profile 
            _profileHeader.phVersion = 0;            // profile format version number 
            _profileHeader.phClass = 0;              // type of profile
            _profileHeader.phDataColorSpace = 0;     // color space of data 
            _profileHeader.phConnectionSpace = 0;    // PCS
            _profileHeader.phDateTime_0 = 0;         // date profile was created
            _profileHeader.phDateTime_1 = 0;         // date profile was created
            _profileHeader.phDateTime_2 = 0;         // date profile was created 
            _profileHeader.phSignature = 0;          // magic number
            _profileHeader.phPlatform = 0;           // primary platform 
            _profileHeader.phProfileFlags = 0;       // various bit settings 
            _profileHeader.phManufacturer = 0;       // device manufacturer
            _profileHeader.phModel = 0;              // device model number 
            _profileHeader.phAttributes_0 = 0;       // device attributes
            _profileHeader.phAttributes_1 = 0;       // device attributes
            _profileHeader.phRenderingIntent = 0;    // rendering intent
            _profileHeader.phIlluminant_0 = 0;       // profile illuminant 
            _profileHeader.phIlluminant_1 = 0;       // profile illuminant
            _profileHeader.phIlluminant_2 = 0;       // profile illuminant 
            _profileHeader.phCreator = 0;            // profile creator 
            _profileHeader.phReserved = IntPtr.Zero; // reserved for future use
        } 

        /// 
        /// Create a ColorContext from an unmanaged color context
        ///  
        /// 
        /// SecurityCritical: This code sets a critical data member 
        /// SecurityTreatAsSafe: Handle is SafeMILHandle that cannot be constructed with an arbitrary IntPtr 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal ColorContext(SafeMILHandle colorContextHandle)
        {
            _profileHash = 9999;    // ISSUE: Is this correct?
            _colorContextHandle = colorContextHandle; 
        }
 
        ///  
        /// Creates a new ColorContext object from a .icm or .icc color profile specified by profileUri.
        ///  
        /// Specifies the URI of a color profile used by the newly created ColorContext.
        public ColorContext(Uri profileUri)
        {
            Initialize(profileUri, /* isStandardProfileUriNotFromUser = */ false); 
        }
 
        ///  
        /// Given a pixel format, this function will return the closest standard color space (sRGB, scRGB, etc)
        ///  
        /// SecurityCritical: Calls the SecurityCritical method GetStandardColorSpaceProfile()
        /// PublicOK: doesn't reveal any sensitive information
        /// 
        ///  
        [SecurityCritical]
        public ColorContext(PixelFormat pixelFormat) 
        { 
            switch (pixelFormat.Format)
            { 
                case PixelFormatEnum.Default:
                case PixelFormatEnum.Indexed1:
                case PixelFormatEnum.Indexed2:
                case PixelFormatEnum.Indexed4: 
                case PixelFormatEnum.Indexed8:
                case PixelFormatEnum.Bgr555: 
                case PixelFormatEnum.Bgr565: 
                case PixelFormatEnum.Bgr24:
                case PixelFormatEnum.Rgb24: 
                case PixelFormatEnum.Bgr32:
                case PixelFormatEnum.Bgra32:
                case PixelFormatEnum.Pbgra32:
                default: 
                    Initialize(GetStandardColorSpaceProfile(), /* isStandardProfileUriNotFromUser = */ true);
                    break; 
 
                case PixelFormatEnum.Rgba64:
                case PixelFormatEnum.Prgba64: 
                case PixelFormatEnum.Rgba128Float:
                case PixelFormatEnum.Prgba128Float:
                case PixelFormatEnum.BlackWhite:
                case PixelFormatEnum.Gray2: 
                case PixelFormatEnum.Gray4:
                case PixelFormatEnum.Gray8: 
                case PixelFormatEnum.Gray32Float: 
                case PixelFormatEnum.Cmyk32:
                    throw new NotSupportedException(); // standard scRGB profile does not exist yet 
            }
        }

        #endregion 

        #region Public Methods 
 
        /// 
        /// Data 
        /// 
        /// 
        /// SecurityCritical: This code calls critical code (unmanaged)
        /// PublicOK: Calls to retrieve safe data. Additionally AllocHGlobal is happening here 
        ///                      so no need to demand permissions
        ///  
        [SecurityCritical] 
        public Stream OpenProfileStream()
        { 
            IntPtr pdwSize = IntPtr.Zero;
            IntPtr pBuffer = IntPtr.Zero;
            byte[] prb = new byte[1];
 
            try
            { 
                pdwSize = Marshal.AllocHGlobal((int)sizeof(int)); 

                Marshal.WriteInt32(pdwSize, (int)0); 

                _colorContextHelper.GetColorProfileFromHandle(IntPtr.Zero, pdwSize);

                pBuffer = Marshal.AllocHGlobal(Marshal.ReadInt32(pdwSize)); 

                _colorContextHelper.GetColorProfileFromHandle(pBuffer, pdwSize); 
 
                prb = new byte[Marshal.ReadInt32(pdwSize)];
 
                Marshal.Copy(pBuffer, prb, 0, Marshal.ReadInt32(pdwSize));
            }
            finally
            { 
                if (pdwSize!=IntPtr.Zero)
                { 
                    Marshal.FreeHGlobal(pdwSize); 
                }
                if (pBuffer!=IntPtr.Zero) 
                {
                    Marshal.FreeHGlobal(pBuffer);
                }
            } 

            return new MemoryStream(prb); 
        } 

        #endregion Public Methods 

        #region Public Properties

        ///  
        /// ProfileUri
        ///  
        ///  
        /// SecurityCritical: Returns the profile uri which could be a sensitive local path like %WINDIR%
        /// that shouldn't be given out in partial trust 
        /// PublicOK: demands appropriate permissions
        /// 
        public Uri ProfileUri
        { 
            [SecurityCritical]
            get 
            { 
                Uri uri = _profileUri.Value;
 
                //
                // We don't need to demand permission if the user gave us the uri because the user
                // already knows the value. If the user didn't give us the value, then the uri has
                // to be a file path because we got it from GetStandardColorSpaceProfile 
                //
                if (_isProfileUriNotFromUser.Value) 
                { 
                    Invariant.Assert(uri.IsFile);
 
                    SecurityHelper.DemandPathDiscovery(uri.LocalPath);
                }

                return uri; 
            }
        } 
 
        #endregion Public Properties
 
        #region Internal Properties

        /// 
        /// ProfileHandle 
        /// 
        ///  
        /// SecurityCritical: This comes out of an elevation needs to be critical and tracked. 
        /// 
        internal SafeProfileHandle ProfileHandle 
        {
            [SecurityCritical]
            get
            { 
                return _colorContextHelper.ProfileHandle;
            } 
        } 

        ///  
        /// ColorContextHandleHandle
        /// 
        /// 
        /// SecurityCritical: Retrieves a critical data member (unmanaged pointer) 
        /// SecurityTreatAsSafe: Its ok to give the SafeMILHandle out (since no set is allowed)
        ///  
        internal SafeMILHandle ColorContextHandle 
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            {
                return _colorContextHandle;
            } 
        }
 
 
        /// 
        /// NumChannels 
        /// 
        /// 
        /// SecurityCritical: This code reference critical data
        /// SecurityTreatAsSafe: Even it reference the critical data but it only check it is null or valid 
        ///                      return data (_numChannels) is safe
        ///  
        internal int NumChannels 
        {
 
            [SecurityCritical, SecurityTreatAsSafe]
            get
            {
                if (_colorContextHelper.IsInvalid) // sRGB or scRGB 
                    return 3;
 
                return _numChannels; 
            }
        } 

        /// 
        /// ColorType
        ///  
        internal UInt32 ColorType
        { 
            get 
            {
                return (UInt32)_colorTypeFromChannels[NumChannels]; 
            }
        }

        ///  
        /// ColorSpaceFamily
        ///  
        ///  
        /// SecurityCritical: This code reference critical data
        /// SecurityTreatAsSafe: Even it reference the critical data but it only check it is null or valid 
        ///                      return data (_colorSpaceFamily) is safe
        /// 
        internal StandardColorSpace ColorSpaceFamily
        { 
            [SecurityCritical, SecurityTreatAsSafe]
            get 
            { 
                if (_colorContextHelper.IsInvalid) // sRGB or scRGB
                { 
                    return StandardColorSpace.Srgb;
                }
                else
                { 
                    return _colorSpaceFamily;
                } 
            } 
        }
 
        #endregion


        //----------------------------------------------------- 
        //
        //  Equality Methods/Properties 
        // 
        //-----------------------------------------------------
 
        #region Equality methods and Properties

        /// 
        /// Equals method 
        /// 
        override public bool Equals(object obj ) 
        { 
            ColorContext context = obj as ColorContext;
 
            return (context == this);
        }

        ///  
        /// GetHashCode
        ///  
        override public int GetHashCode() 
        {
            return (int)_profileHash; 
        }

        /// 
        /// Operator== 
        /// 
        public static bool operator==(ColorContext context1, ColorContext context2) 
        { 
            object obj1 = context1;
            object obj2 = context2; 

            if (obj1 == null && obj2 == null)
            {
                return true; 
            }
            else if (obj1 != null && obj2 != null) 
            { 
                #pragma warning disable 6506
                return ( 
                    (context1._profileHeader.phSize == context2._profileHeader.phSize) &&
                    (context1._profileHeader.phCMMType == context2._profileHeader.phCMMType) &&
                    (context1._profileHeader.phVersion == context2._profileHeader.phVersion) &&
                    (context1._profileHeader.phClass == context2._profileHeader.phClass) && 
                    (context1._profileHeader.phDataColorSpace == context2._profileHeader.phDataColorSpace) &&
                    (context1._profileHeader.phConnectionSpace == context2._profileHeader.phConnectionSpace) && 
                    (context1._profileHeader.phDateTime_0 == context2._profileHeader.phDateTime_0) && 
                    (context1._profileHeader.phDateTime_1 == context2._profileHeader.phDateTime_1) &&
                    (context1._profileHeader.phDateTime_2 == context2._profileHeader.phDateTime_2) && 
                    (context1._profileHeader.phSignature == context2._profileHeader.phSignature) &&
                    (context1._profileHeader.phPlatform == context2._profileHeader.phPlatform) &&
                    (context1._profileHeader.phProfileFlags == context2._profileHeader.phProfileFlags) &&
                    (context1._profileHeader.phManufacturer == context2._profileHeader.phManufacturer) && 
                    (context1._profileHeader.phModel == context2._profileHeader.phModel) &&
                    (context1._profileHeader.phAttributes_0 == context2._profileHeader.phAttributes_0) && 
                    (context1._profileHeader.phAttributes_1 == context2._profileHeader.phAttributes_1) && 
                    (context1._profileHeader.phRenderingIntent == context2._profileHeader.phRenderingIntent) &&
                    (context1._profileHeader.phIlluminant_0 == context2._profileHeader.phIlluminant_0) && 
                    (context1._profileHeader.phIlluminant_1 == context2._profileHeader.phIlluminant_1) &&
                    (context1._profileHeader.phIlluminant_2 == context2._profileHeader.phIlluminant_2) &&
                    (context1._profileHeader.phCreator == context2._profileHeader.phCreator)
                    ); 
                #pragma warning restore 6506
            } 
            else 
            {
                return false; 
            }
        }

        ///  
        /// Operator!=
        ///  
        public static bool operator!=(ColorContext context1, ColorContext context2) 
        {
            return !(context1 == context2); 
        }

        #endregion
 
        #region Private Methods
 
        ///  
        /// Loads color profile given by profileUri
        ///  
        /// 
        /// SecurityCritical: method calls SecurityCritical code, profileUri could contain
        /// sensitive path information
        /// SecurityTreatAsSafe: WebRequest demands the necessary permissions 
        /// and the Uri isn't exposed
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        private void Initialize(Uri profileUri, bool isStandardProfileUriNotFromUser)
        { 
            bool tryProfileFromResource = false;

            if (profileUri == null)
            { 
                throw new ArgumentNullException("profileUri");
            } 
 
            if (!profileUri.IsAbsoluteUri)
            { 
                throw new ArgumentException(SR.Get(SRID.UriNotAbsolute), "profileUri");
            }

            _profileUri = new SecurityCriticalData(profileUri); 
            _isProfileUriNotFromUser = new SecurityCriticalDataForSet(isStandardProfileUriNotFromUser);
 
            Stream profileStream = null; 

            try 
            {
                profileStream = WpfWebRequestHelper.CreateRequestAndGetResponseStream(profileUri);
            }
            catch (WebException) 
            {
                // 
                // If we couldn't load the system's default color profile (e.g. in partial trust), load a color profile from 
                // a resource so the image shows up at least. If the user specified a color profile and we weren't
                // able to load it, we'll fail to avoid letting the user use this resource fallback as a way to discover 
                // files on disk.
                //
                if (isStandardProfileUriNotFromUser)
                { 
                    tryProfileFromResource = true;
                } 
            } 

            if (profileStream == null) 
            {
                if (tryProfileFromResource)
                {
                    ResourceManager resourceManager = new ResourceManager(_colorProfileResources, Assembly.GetAssembly(typeof(ColorContext))); 
                    byte[] sRGBProfile = (byte[])resourceManager.GetObject(_sRGBProfileName);
 
                    profileStream = new MemoryStream(sRGBProfile); 
                }
                else 
                {
                    //
                    // SECURITY WARNING: This exception includes the profile URI which may contain sensitive information. However, as of right now,
                    // this is safe because it can only happen when the URI is given to us by the user. 
                    //
                    Invariant.Assert(!isStandardProfileUriNotFromUser); 
                    throw new FileNotFoundException(SR.Get(SRID.FileNotFoundExceptionWithFileName, profileUri.AbsolutePath), profileUri.AbsolutePath); 
                }
            } 

            FromStream(profileStream, profileUri.AbsolutePath);
        }
 
        /// 
        /// Obtains the system color profile path 
        ///  
        /// 
        /// SecurityCritical: This code calls critical code (unmanaged) and returns 
        /// path information that can be set by an outside party and/or may include
        /// sensitive paths like %WINDIR%
        /// 
        [SecurityCritical] 
        private static Uri GetStandardColorSpaceProfile()
        { 
            const int SIZE = NativeMethods.MAX_PATH; 

            uint dwProfileID = (uint)ICMConstants.sRGB; 
            uint bufferSize = SIZE;
            StringBuilder buffer = new StringBuilder(SIZE);

            HRESULT.Check(UnsafeNativeMethods.Mscms.GetStandardColorSpaceProfile(IntPtr.Zero, dwProfileID, buffer, out bufferSize)); 

            Uri profilePath; 
            string profilePathString = buffer.ToString(); 

            if (!Uri.TryCreate(profilePathString, UriKind.Absolute, out profilePath)) 
            {
                //
                // GetStandardColorSpaceProfile() returns whatever was given to SetStandardColorSpaceProfile().
                // If it were set to a relative path by the user, we should throw an exception to avoid any possible 
                // security issues. However, the Vista control panel uses the same API and sometimes likes to set
                // relative paths. Since we can't tell the difference and we want people to be able to change 
                // their color profile from the control panel, we'll tack on the system directory. 
                //
 
                // bufferSize was modified by GetStandardColorSpaceProfile so set it again
                bufferSize = SIZE;

                HRESULT.Check(UnsafeNativeMethods.Mscms.GetColorDirectory(IntPtr.Zero, buffer, out bufferSize)); 

                profilePath = new Uri(Path.Combine(buffer.ToString(), profilePathString)); 
            } 

            return profilePath; 
        }

        private void FromStream(Stream stm, string filename)
        { 
            Debug.Assert(stm != null);
 
            int bufferSize = _bufferSizeIncrement; 

            if (stm.CanSeek) 
            {
                bufferSize = (int)stm.Length + 1; // If this stream is seekable (most cases), we will only have one buffer alloc and read below
                                                // otherwise, we will incrementally grow the buffer and read until end of profile.
                                                // profiles are typcially small, so usually one allocation will suffice 
            }
 
            byte[] rawBytes = new byte[bufferSize]; 
            int numBytesRead = 0;
            while (bufferSize < _maximumColorContextLength) 
            {
                numBytesRead += stm.Read(rawBytes, numBytesRead, bufferSize-numBytesRead);

                if (numBytesRead < bufferSize) 
                {
                    FromRawBytes(rawBytes, numBytesRead); 
 
                    // Create the ColorContextHandle
                    GetColorContextHandlerFromProfileBytes(rawBytes, numBytesRead); 

                    return;
                }
                else 
                {
                    bufferSize += _bufferSizeIncrement; 
                    byte[] newRawBytes = new byte[bufferSize]; 
                    rawBytes.CopyTo(newRawBytes, 0);
                    rawBytes = newRawBytes; 
                }
            }

            throw new ArgumentException(SR.Get(SRID.ColorContext_FileTooLarge), filename); 
        }
 
        ///  
        /// SecurityCritical: This code calls critical code (unmanaged)
        /// SecurityTreatAsSafe: Calls to retrieve safe data. Additionally AllocHGlobal is happening here 
        ///                      so no need to demand permissions
        /// 
        [SecurityCritical,SecurityTreatAsSafe]
        private void FromRawBytes(byte[] data, int dataLength)  // Note: often the data buffer is larger than the actual data in it. 
        {
            // Technically, we should only compute our hash on the data in the buffer that is valid. 
            // However, it shouldn't really matter - the rest of the buffer is cleared when the 
            // managed array is allocated.  And changing this method requires updating asmmeta and
            // such, which we may not want to do for an SP fix. 
            Crc32Helper crc32 = new Crc32Helper();
            crc32.ComputeCrc32(data);
            _profileHash = crc32.Crc32Value;
 
            profileStruct profileStruct;
            IntPtr pColorSpaceFamily = IntPtr.Zero; 
            IntPtr pNumChannels = IntPtr.Zero; 
            profileStruct.dwType = (UInt32)ICMConstants.PROFILE_MEMBUFFER;
            int ndataLength = dataLength; 
            profileStruct.cbDataSize = (uint)ndataLength;

            IntPtr pProfile = IntPtr.Zero;
            IntPtr pHeader = IntPtr.Zero; 

            try 
            { 
                profileStruct.pProfileData = Marshal.AllocHGlobal(ndataLength);
                Marshal.Copy(data, 0, profileStruct.pProfileData, ndataLength); 
                pProfile = Marshal.AllocHGlobal(sizeOfProfile());
                Marshal.StructureToPtr(profileStruct, pProfile, true);

                Initialize(); 

                _colorContextHelper.OpenColorProfile(pProfile); 
 
                pHeader = Marshal.AllocHGlobal(256);
                _colorContextHelper.GetColorProfileHeader(pHeader); 

                _profileHeader = (ProfileHeaderStruct)Marshal.PtrToStructure(pHeader, typeof(ProfileHeaderStruct));
            }
            finally 
            {
                Marshal.FreeHGlobal(pProfile); 
                pProfile = IntPtr.Zero; 
                Marshal.FreeHGlobal(pHeader);
                pHeader = IntPtr.Zero; 
            }

            if (profileStruct.pProfileData != IntPtr.Zero)
            { 
                Marshal.FreeHGlobal(profileStruct.pProfileData);
                profileStruct.pProfileData = IntPtr.Zero; 
            } 

            switch ((ICMConstants)_profileHeader.phDataColorSpace) 
            {
                case ICMConstants.XYZ:
                case ICMConstants.Lab:
                case ICMConstants.Luv: 
                case ICMConstants.YCbr:
                case ICMConstants.Yxy: 
                case ICMConstants.HSV: 
                case ICMConstants.HLS:
                case ICMConstants.CMY: 
                    _numChannels = 3;
                    _colorSpaceFamily = StandardColorSpace.Unknown;
                    break;
                case ICMConstants.RGB: 
                    _colorSpaceFamily = StandardColorSpace.Rgb;
                    _numChannels = 3; 
                    break; 
                case ICMConstants.GRAY:
                    _colorSpaceFamily = StandardColorSpace.Gray; 
                    _numChannels = 1;
                    break;
                case ICMConstants.CMYK:
                    _colorSpaceFamily = StandardColorSpace.Cmyk; 
                    _numChannels = 4;
                    break; 
                case ICMConstants._2CLR: 
                    _colorSpaceFamily = StandardColorSpace.Multichannel;
                    _numChannels = 2; 
                    break;
                case ICMConstants._3CLR:
                    _colorSpaceFamily = StandardColorSpace.Multichannel;
                    _numChannels = 3; 
                    break;
                case ICMConstants._4CLR: 
                    _colorSpaceFamily = StandardColorSpace.Multichannel; 
                    _numChannels = 4;
                    break; 
                case ICMConstants._5CLR:
                    _numChannels = 5;
                    _colorSpaceFamily = StandardColorSpace.Multichannel;
                    break; 
                case ICMConstants._6CLR:
                    _numChannels = 6; 
                    _colorSpaceFamily = StandardColorSpace.Multichannel; 
                    break;
                case ICMConstants._7CLR: 
                    _numChannels = 7;
                    _colorSpaceFamily = StandardColorSpace.Multichannel;
                    break;
                case ICMConstants._8CLR: 
                    _numChannels = 8;
                    _colorSpaceFamily = StandardColorSpace.Multichannel; 
                    break; 
                case ICMConstants._9CLR:
                    _numChannels = 9; 
                    _colorSpaceFamily = StandardColorSpace.Multichannel;
                    break;
                case ICMConstants.ACLR:
                    _numChannels = 10; 
                    _colorSpaceFamily = StandardColorSpace.Multichannel;
                    break; 
                case ICMConstants.BCLR: 
                    _numChannels = 11;
                    _colorSpaceFamily = StandardColorSpace.Multichannel; 
                    break;
                case ICMConstants.CCLR:
                    _numChannels = 12;
                    _colorSpaceFamily = StandardColorSpace.Multichannel; 
                    break;
                case ICMConstants.DCLR: 
                    _numChannels = 13; 
                    _colorSpaceFamily = StandardColorSpace.Multichannel;
                    break; 
                case ICMConstants.ECLR:
                    _numChannels = 14;
                    _colorSpaceFamily = StandardColorSpace.Multichannel;
                    break; 
                case ICMConstants.FCLR:
                    _numChannels = 15; 
                    _colorSpaceFamily = StandardColorSpace.Multichannel; 
                    break;
                default: 
                    _numChannels = 0;
                    _colorSpaceFamily = StandardColorSpace.Unknown;
                    break;
            } 
        }
 
        ///  
        /// SecurityCritical: This code calls critical code (unmanaged)
        /// SecurityTreatAsSafe: Calls to retrieve safe data. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private void GetColorContextHandlerFromProfileBytes(byte[] pProfileBytes, int nNumberofProfileBytes)
        { 
            IntPtr pBuffer = IntPtr.Zero;
 
            try 
            {
                using (FactoryMaker factoryMaker = new FactoryMaker()) 
                {
                    HRESULT.Check(UnsafeNativeMethods.WICCodec.CreateColorContext(factoryMaker.ImagingFactoryPtr, out _colorContextHandle));

                    pBuffer = Marshal.AllocHGlobal(nNumberofProfileBytes); 

                    Marshal.Copy(pProfileBytes, 0, pBuffer, nNumberofProfileBytes); 
 
                    HRESULT.Check(UnsafeNativeMethods.WICCodec.ColorContext_InitializeFromMemory(_colorContextHandle, pBuffer, (UInt32)nNumberofProfileBytes));
                } 

            }
            finally
            { 
                Marshal.FreeHGlobal(pBuffer);
                pBuffer = IntPtr.Zero; 
            } 
        }
 
        unsafe private int sizeOfProfile()
        {
            return (sizeof(profileStruct));
        } 

        ///  
        /// SecurityCritical: This code calls critical code (unmanaged) 
        /// 
        [SecurityCritical] 
        private void Initialize()
        {
            _colorContextHelper = new ColorContextHelper();
        } 

        #endregion 
 
        #region Private Fields
 
        internal struct profileStruct
        {
            public UInt32 dwType;             // profile type
            public IntPtr pProfileData;       // it is profile bytes buffer containing color profile profile 
                                              // we have our own copy instead of retain to the unmanaged code
            public UInt32 cbDataSize;         // size of profile data 
        }; 

        ///  
        /// SecurityCritical: This comes out of an elevation needs to be critical and tracked.
        /// 
        [SecurityCritical]
        private ColorContextHelper _colorContextHelper; 

        private StandardColorSpace _colorSpaceFamily; 
 
        private int _numChannels;
 
        /// 
        /// SecurityCritical: May contain sensitive path information like %WINDIR%
        /// 
        private SecurityCriticalData _profileUri; 

        ///  
        /// SecurityCritical: Determines whether or not _profileUri contains sensitive data 
        /// that we need to demand access to
        ///  
        private SecurityCriticalDataForSet _isProfileUriNotFromUser;

        private struct ProfileHeaderStruct
        { 
            public uint phSize;             // profile size in bytes
            public uint phCMMType;          // CMM for this profile 
            public uint phVersion;          // profile format version number 
            public uint phClass;            // type of profile
            public uint phDataColorSpace;   // color space of data 
            public uint phConnectionSpace;  // PCS
            public uint phDateTime_0;       // date profile was created
            public uint phDateTime_1;       // date profile was created
            public uint phDateTime_2;       // date profile was created 
            public uint phSignature;        // magic number
            public uint phPlatform;         // primary platform 
            public uint phProfileFlags;     // various bit settings 
            public uint phManufacturer;     // device manufacturer
            public uint phModel;            // device model number 
            public uint phAttributes_0;     // device attributes
            public uint phAttributes_1;     // device attributes
            public uint phRenderingIntent;  // rendering intent
            public uint phIlluminant_0;     // profile illuminant 
            public uint phIlluminant_1;     // profile illuminant
            public uint phIlluminant_2;     // profile illuminant 
            public uint phCreator;          // profile creator 
            public IntPtr phReserved;       // reserved for future use
        }; 

        private UInt32 _profileHash;

        private ProfileHeaderStruct _profileHeader; 

        ///  
        /// SecurityCritical: Unmanaged ColorContext handle 
        /// 
        [SecurityCritical] 
        private SafeMILHandle _colorContextHandle;

        private const int _bufferSizeIncrement = 1024 * 1024;  // 1 Mb
 
        private const int _maximumColorContextLength = _bufferSizeIncrement * 32; // 32 Mb
 
        private static ICMConstants[] _colorTypeFromChannels = 
            new ICMConstants[9] {
                ICMConstants.COLORTYPE_UNDEFINED, 
                ICMConstants.COLORTYPE_UNDEFINED,
                ICMConstants.COLORTYPE_UNDEFINED,
                ICMConstants.COLOR_3_CHANNEL,
                ICMConstants.COLOR_CMYK, 
                ICMConstants.COLOR_5_CHANNEL,
                ICMConstants.COLOR_6_CHANNEL, 
                ICMConstants.COLOR_7_CHANNEL, 
                ICMConstants.COLOR_8_CHANNEL
                }; 

        private static string _colorProfileResources = "ColorProfiles";

        private static string _sRGBProfileName = "sRGB_icm"; 

        internal enum StandardColorSpace : int 
        { 
            Unknown = 0,
            Srgb = 1, 
            ScRgb = 2,
            Rgb = 3,
            Cmyk = 4,
            Gray = 6, 
            Multichannel = 7
        } 
 
        private enum ICMConstants : uint
        { 
            PROFILE_MEMBUFFER = 2,

            COLORTYPE_UNDEFINED = 0xFF,
            COLORTYPE_RGB       = 2, 

            COLOR_3_CHANNEL = 6, 
            COLOR_CMYK      = 7, 
            COLOR_5_CHANNEL = 8,
            COLOR_6_CHANNEL = 9, 
            COLOR_7_CHANNEL = 10,
            COLOR_8_CHANNEL = 11,

            sRGB  = 0x73524742, 
            XYZ   = 0x58595A20,
            Lab   = 0x4C616220, 
            Luv   = 0x4C757620, 
            YCbr  = 0x59436272,
            Yxy   = 0x59787920, 
            HSV   = 0x48535620,
            HLS   = 0x484C5320,
            CMY   = 0x434D5920,
            RGB   = 0x52474220, 
            GRAY  = 0x47524159,
            CMYK  = 0x434D594B, 
            _2CLR = 0x32434C52, 
            _3CLR = 0x33434C52,
            _4CLR = 0x34434C52, 
            _5CLR = 0x35434C52,
            _6CLR = 0x36434C52,
            _7CLR = 0x37434C52,
            _8CLR = 0x38434C52, 
            _9CLR = 0x39434C52,
            ACLR  = 0x41434C52, 
            BCLR  = 0x42434C52, 
            CCLR  = 0x43434C52,
            DCLR  = 0x44434C52, 
            ECLR  = 0x45434C52,
            FCLR  = 0x46434C52
        }
 
        #endregion
    } 
} 

 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------ 
//  Microsoft Windows Client Platform
//  Copyright (c) Microsoft Corporation, All Rights Reserved.
//
//  File: ColorContext.cs 
//-----------------------------------------------------------------------------
#pragma warning disable 1634, 1691 // Allow suppression of certain presharp messages 
 
using System;
using MS.Internal; 
using MS.Internal.PresentationCore;
using MS.Win32;
using System.IO;
using System.Runtime.InteropServices; 
using System.Windows.Media;
using System.Resources; 
using System.Security; 
using System.Security.Permissions;
using System.Collections; 
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Reflection;
using System.Diagnostics; 
using System.Globalization;
using Microsoft.Win32.SafeHandles; 
using System.Net; 
using System.IO.Packaging;
using System.Windows.Navigation; 
using System.Diagnostics.CodeAnalysis;
using System.Text;

using SR=MS.Internal.PresentationCore.SR; 
using SRID=MS.Internal.PresentationCore.SRID;
using UnsafeNativeMethods=MS.Win32.PresentationCore.UnsafeNativeMethods; 
 
namespace System.Windows.Media
{ 
    /// 
    /// Color Context
    /// 
    public class ColorContext 
    {
 
        #region Constructors 

        ///  
        /// Don't allow construction of ColorContext with no params.
        /// 
        private ColorContext()
        { 
            _profileHeader.phSize = 0;               // profile size in bytes
            _profileHeader.phCMMType = 0;            // CMM for this profile 
            _profileHeader.phVersion = 0;            // profile format version number 
            _profileHeader.phClass = 0;              // type of profile
            _profileHeader.phDataColorSpace = 0;     // color space of data 
            _profileHeader.phConnectionSpace = 0;    // PCS
            _profileHeader.phDateTime_0 = 0;         // date profile was created
            _profileHeader.phDateTime_1 = 0;         // date profile was created
            _profileHeader.phDateTime_2 = 0;         // date profile was created 
            _profileHeader.phSignature = 0;          // magic number
            _profileHeader.phPlatform = 0;           // primary platform 
            _profileHeader.phProfileFlags = 0;       // various bit settings 
            _profileHeader.phManufacturer = 0;       // device manufacturer
            _profileHeader.phModel = 0;              // device model number 
            _profileHeader.phAttributes_0 = 0;       // device attributes
            _profileHeader.phAttributes_1 = 0;       // device attributes
            _profileHeader.phRenderingIntent = 0;    // rendering intent
            _profileHeader.phIlluminant_0 = 0;       // profile illuminant 
            _profileHeader.phIlluminant_1 = 0;       // profile illuminant
            _profileHeader.phIlluminant_2 = 0;       // profile illuminant 
            _profileHeader.phCreator = 0;            // profile creator 
            _profileHeader.phReserved = IntPtr.Zero; // reserved for future use
        } 

        /// 
        /// Create a ColorContext from an unmanaged color context
        ///  
        /// 
        /// SecurityCritical: This code sets a critical data member 
        /// SecurityTreatAsSafe: Handle is SafeMILHandle that cannot be constructed with an arbitrary IntPtr 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal ColorContext(SafeMILHandle colorContextHandle)
        {
            _profileHash = 9999;    // ISSUE: Is this correct?
            _colorContextHandle = colorContextHandle; 
        }
 
        ///  
        /// Creates a new ColorContext object from a .icm or .icc color profile specified by profileUri.
        ///  
        /// Specifies the URI of a color profile used by the newly created ColorContext.
        public ColorContext(Uri profileUri)
        {
            Initialize(profileUri, /* isStandardProfileUriNotFromUser = */ false); 
        }
 
        ///  
        /// Given a pixel format, this function will return the closest standard color space (sRGB, scRGB, etc)
        ///  
        /// SecurityCritical: Calls the SecurityCritical method GetStandardColorSpaceProfile()
        /// PublicOK: doesn't reveal any sensitive information
        /// 
        ///  
        [SecurityCritical]
        public ColorContext(PixelFormat pixelFormat) 
        { 
            switch (pixelFormat.Format)
            { 
                case PixelFormatEnum.Default:
                case PixelFormatEnum.Indexed1:
                case PixelFormatEnum.Indexed2:
                case PixelFormatEnum.Indexed4: 
                case PixelFormatEnum.Indexed8:
                case PixelFormatEnum.Bgr555: 
                case PixelFormatEnum.Bgr565: 
                case PixelFormatEnum.Bgr24:
                case PixelFormatEnum.Rgb24: 
                case PixelFormatEnum.Bgr32:
                case PixelFormatEnum.Bgra32:
                case PixelFormatEnum.Pbgra32:
                default: 
                    Initialize(GetStandardColorSpaceProfile(), /* isStandardProfileUriNotFromUser = */ true);
                    break; 
 
                case PixelFormatEnum.Rgba64:
                case PixelFormatEnum.Prgba64: 
                case PixelFormatEnum.Rgba128Float:
                case PixelFormatEnum.Prgba128Float:
                case PixelFormatEnum.BlackWhite:
                case PixelFormatEnum.Gray2: 
                case PixelFormatEnum.Gray4:
                case PixelFormatEnum.Gray8: 
                case PixelFormatEnum.Gray32Float: 
                case PixelFormatEnum.Cmyk32:
                    throw new NotSupportedException(); // standard scRGB profile does not exist yet 
            }
        }

        #endregion 

        #region Public Methods 
 
        /// 
        /// Data 
        /// 
        /// 
        /// SecurityCritical: This code calls critical code (unmanaged)
        /// PublicOK: Calls to retrieve safe data. Additionally AllocHGlobal is happening here 
        ///                      so no need to demand permissions
        ///  
        [SecurityCritical] 
        public Stream OpenProfileStream()
        { 
            IntPtr pdwSize = IntPtr.Zero;
            IntPtr pBuffer = IntPtr.Zero;
            byte[] prb = new byte[1];
 
            try
            { 
                pdwSize = Marshal.AllocHGlobal((int)sizeof(int)); 

                Marshal.WriteInt32(pdwSize, (int)0); 

                _colorContextHelper.GetColorProfileFromHandle(IntPtr.Zero, pdwSize);

                pBuffer = Marshal.AllocHGlobal(Marshal.ReadInt32(pdwSize)); 

                _colorContextHelper.GetColorProfileFromHandle(pBuffer, pdwSize); 
 
                prb = new byte[Marshal.ReadInt32(pdwSize)];
 
                Marshal.Copy(pBuffer, prb, 0, Marshal.ReadInt32(pdwSize));
            }
            finally
            { 
                if (pdwSize!=IntPtr.Zero)
                { 
                    Marshal.FreeHGlobal(pdwSize); 
                }
                if (pBuffer!=IntPtr.Zero) 
                {
                    Marshal.FreeHGlobal(pBuffer);
                }
            } 

            return new MemoryStream(prb); 
        } 

        #endregion Public Methods 

        #region Public Properties

        ///  
        /// ProfileUri
        ///  
        ///  
        /// SecurityCritical: Returns the profile uri which could be a sensitive local path like %WINDIR%
        /// that shouldn't be given out in partial trust 
        /// PublicOK: demands appropriate permissions
        /// 
        public Uri ProfileUri
        { 
            [SecurityCritical]
            get 
            { 
                Uri uri = _profileUri.Value;
 
                //
                // We don't need to demand permission if the user gave us the uri because the user
                // already knows the value. If the user didn't give us the value, then the uri has
                // to be a file path because we got it from GetStandardColorSpaceProfile 
                //
                if (_isProfileUriNotFromUser.Value) 
                { 
                    Invariant.Assert(uri.IsFile);
 
                    SecurityHelper.DemandPathDiscovery(uri.LocalPath);
                }

                return uri; 
            }
        } 
 
        #endregion Public Properties
 
        #region Internal Properties

        /// 
        /// ProfileHandle 
        /// 
        ///  
        /// SecurityCritical: This comes out of an elevation needs to be critical and tracked. 
        /// 
        internal SafeProfileHandle ProfileHandle 
        {
            [SecurityCritical]
            get
            { 
                return _colorContextHelper.ProfileHandle;
            } 
        } 

        ///  
        /// ColorContextHandleHandle
        /// 
        /// 
        /// SecurityCritical: Retrieves a critical data member (unmanaged pointer) 
        /// SecurityTreatAsSafe: Its ok to give the SafeMILHandle out (since no set is allowed)
        ///  
        internal SafeMILHandle ColorContextHandle 
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            {
                return _colorContextHandle;
            } 
        }
 
 
        /// 
        /// NumChannels 
        /// 
        /// 
        /// SecurityCritical: This code reference critical data
        /// SecurityTreatAsSafe: Even it reference the critical data but it only check it is null or valid 
        ///                      return data (_numChannels) is safe
        ///  
        internal int NumChannels 
        {
 
            [SecurityCritical, SecurityTreatAsSafe]
            get
            {
                if (_colorContextHelper.IsInvalid) // sRGB or scRGB 
                    return 3;
 
                return _numChannels; 
            }
        } 

        /// 
        /// ColorType
        ///  
        internal UInt32 ColorType
        { 
            get 
            {
                return (UInt32)_colorTypeFromChannels[NumChannels]; 
            }
        }

        ///  
        /// ColorSpaceFamily
        ///  
        ///  
        /// SecurityCritical: This code reference critical data
        /// SecurityTreatAsSafe: Even it reference the critical data but it only check it is null or valid 
        ///                      return data (_colorSpaceFamily) is safe
        /// 
        internal StandardColorSpace ColorSpaceFamily
        { 
            [SecurityCritical, SecurityTreatAsSafe]
            get 
            { 
                if (_colorContextHelper.IsInvalid) // sRGB or scRGB
                { 
                    return StandardColorSpace.Srgb;
                }
                else
                { 
                    return _colorSpaceFamily;
                } 
            } 
        }
 
        #endregion


        //----------------------------------------------------- 
        //
        //  Equality Methods/Properties 
        // 
        //-----------------------------------------------------
 
        #region Equality methods and Properties

        /// 
        /// Equals method 
        /// 
        override public bool Equals(object obj ) 
        { 
            ColorContext context = obj as ColorContext;
 
            return (context == this);
        }

        ///  
        /// GetHashCode
        ///  
        override public int GetHashCode() 
        {
            return (int)_profileHash; 
        }

        /// 
        /// Operator== 
        /// 
        public static bool operator==(ColorContext context1, ColorContext context2) 
        { 
            object obj1 = context1;
            object obj2 = context2; 

            if (obj1 == null && obj2 == null)
            {
                return true; 
            }
            else if (obj1 != null && obj2 != null) 
            { 
                #pragma warning disable 6506
                return ( 
                    (context1._profileHeader.phSize == context2._profileHeader.phSize) &&
                    (context1._profileHeader.phCMMType == context2._profileHeader.phCMMType) &&
                    (context1._profileHeader.phVersion == context2._profileHeader.phVersion) &&
                    (context1._profileHeader.phClass == context2._profileHeader.phClass) && 
                    (context1._profileHeader.phDataColorSpace == context2._profileHeader.phDataColorSpace) &&
                    (context1._profileHeader.phConnectionSpace == context2._profileHeader.phConnectionSpace) && 
                    (context1._profileHeader.phDateTime_0 == context2._profileHeader.phDateTime_0) && 
                    (context1._profileHeader.phDateTime_1 == context2._profileHeader.phDateTime_1) &&
                    (context1._profileHeader.phDateTime_2 == context2._profileHeader.phDateTime_2) && 
                    (context1._profileHeader.phSignature == context2._profileHeader.phSignature) &&
                    (context1._profileHeader.phPlatform == context2._profileHeader.phPlatform) &&
                    (context1._profileHeader.phProfileFlags == context2._profileHeader.phProfileFlags) &&
                    (context1._profileHeader.phManufacturer == context2._profileHeader.phManufacturer) && 
                    (context1._profileHeader.phModel == context2._profileHeader.phModel) &&
                    (context1._profileHeader.phAttributes_0 == context2._profileHeader.phAttributes_0) && 
                    (context1._profileHeader.phAttributes_1 == context2._profileHeader.phAttributes_1) && 
                    (context1._profileHeader.phRenderingIntent == context2._profileHeader.phRenderingIntent) &&
                    (context1._profileHeader.phIlluminant_0 == context2._profileHeader.phIlluminant_0) && 
                    (context1._profileHeader.phIlluminant_1 == context2._profileHeader.phIlluminant_1) &&
                    (context1._profileHeader.phIlluminant_2 == context2._profileHeader.phIlluminant_2) &&
                    (context1._profileHeader.phCreator == context2._profileHeader.phCreator)
                    ); 
                #pragma warning restore 6506
            } 
            else 
            {
                return false; 
            }
        }

        ///  
        /// Operator!=
        ///  
        public static bool operator!=(ColorContext context1, ColorContext context2) 
        {
            return !(context1 == context2); 
        }

        #endregion
 
        #region Private Methods
 
        ///  
        /// Loads color profile given by profileUri
        ///  
        /// 
        /// SecurityCritical: method calls SecurityCritical code, profileUri could contain
        /// sensitive path information
        /// SecurityTreatAsSafe: WebRequest demands the necessary permissions 
        /// and the Uri isn't exposed
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        private void Initialize(Uri profileUri, bool isStandardProfileUriNotFromUser)
        { 
            bool tryProfileFromResource = false;

            if (profileUri == null)
            { 
                throw new ArgumentNullException("profileUri");
            } 
 
            if (!profileUri.IsAbsoluteUri)
            { 
                throw new ArgumentException(SR.Get(SRID.UriNotAbsolute), "profileUri");
            }

            _profileUri = new SecurityCriticalData(profileUri); 
            _isProfileUriNotFromUser = new SecurityCriticalDataForSet(isStandardProfileUriNotFromUser);
 
            Stream profileStream = null; 

            try 
            {
                profileStream = WpfWebRequestHelper.CreateRequestAndGetResponseStream(profileUri);
            }
            catch (WebException) 
            {
                // 
                // If we couldn't load the system's default color profile (e.g. in partial trust), load a color profile from 
                // a resource so the image shows up at least. If the user specified a color profile and we weren't
                // able to load it, we'll fail to avoid letting the user use this resource fallback as a way to discover 
                // files on disk.
                //
                if (isStandardProfileUriNotFromUser)
                { 
                    tryProfileFromResource = true;
                } 
            } 

            if (profileStream == null) 
            {
                if (tryProfileFromResource)
                {
                    ResourceManager resourceManager = new ResourceManager(_colorProfileResources, Assembly.GetAssembly(typeof(ColorContext))); 
                    byte[] sRGBProfile = (byte[])resourceManager.GetObject(_sRGBProfileName);
 
                    profileStream = new MemoryStream(sRGBProfile); 
                }
                else 
                {
                    //
                    // SECURITY WARNING: This exception includes the profile URI which may contain sensitive information. However, as of right now,
                    // this is safe because it can only happen when the URI is given to us by the user. 
                    //
                    Invariant.Assert(!isStandardProfileUriNotFromUser); 
                    throw new FileNotFoundException(SR.Get(SRID.FileNotFoundExceptionWithFileName, profileUri.AbsolutePath), profileUri.AbsolutePath); 
                }
            } 

            FromStream(profileStream, profileUri.AbsolutePath);
        }
 
        /// 
        /// Obtains the system color profile path 
        ///  
        /// 
        /// SecurityCritical: This code calls critical code (unmanaged) and returns 
        /// path information that can be set by an outside party and/or may include
        /// sensitive paths like %WINDIR%
        /// 
        [SecurityCritical] 
        private static Uri GetStandardColorSpaceProfile()
        { 
            const int SIZE = NativeMethods.MAX_PATH; 

            uint dwProfileID = (uint)ICMConstants.sRGB; 
            uint bufferSize = SIZE;
            StringBuilder buffer = new StringBuilder(SIZE);

            HRESULT.Check(UnsafeNativeMethods.Mscms.GetStandardColorSpaceProfile(IntPtr.Zero, dwProfileID, buffer, out bufferSize)); 

            Uri profilePath; 
            string profilePathString = buffer.ToString(); 

            if (!Uri.TryCreate(profilePathString, UriKind.Absolute, out profilePath)) 
            {
                //
                // GetStandardColorSpaceProfile() returns whatever was given to SetStandardColorSpaceProfile().
                // If it were set to a relative path by the user, we should throw an exception to avoid any possible 
                // security issues. However, the Vista control panel uses the same API and sometimes likes to set
                // relative paths. Since we can't tell the difference and we want people to be able to change 
                // their color profile from the control panel, we'll tack on the system directory. 
                //
 
                // bufferSize was modified by GetStandardColorSpaceProfile so set it again
                bufferSize = SIZE;

                HRESULT.Check(UnsafeNativeMethods.Mscms.GetColorDirectory(IntPtr.Zero, buffer, out bufferSize)); 

                profilePath = new Uri(Path.Combine(buffer.ToString(), profilePathString)); 
            } 

            return profilePath; 
        }

        private void FromStream(Stream stm, string filename)
        { 
            Debug.Assert(stm != null);
 
            int bufferSize = _bufferSizeIncrement; 

            if (stm.CanSeek) 
            {
                bufferSize = (int)stm.Length + 1; // If this stream is seekable (most cases), we will only have one buffer alloc and read below
                                                // otherwise, we will incrementally grow the buffer and read until end of profile.
                                                // profiles are typcially small, so usually one allocation will suffice 
            }
 
            byte[] rawBytes = new byte[bufferSize]; 
            int numBytesRead = 0;
            while (bufferSize < _maximumColorContextLength) 
            {
                numBytesRead += stm.Read(rawBytes, numBytesRead, bufferSize-numBytesRead);

                if (numBytesRead < bufferSize) 
                {
                    FromRawBytes(rawBytes, numBytesRead); 
 
                    // Create the ColorContextHandle
                    GetColorContextHandlerFromProfileBytes(rawBytes, numBytesRead); 

                    return;
                }
                else 
                {
                    bufferSize += _bufferSizeIncrement; 
                    byte[] newRawBytes = new byte[bufferSize]; 
                    rawBytes.CopyTo(newRawBytes, 0);
                    rawBytes = newRawBytes; 
                }
            }

            throw new ArgumentException(SR.Get(SRID.ColorContext_FileTooLarge), filename); 
        }
 
        ///  
        /// SecurityCritical: This code calls critical code (unmanaged)
        /// SecurityTreatAsSafe: Calls to retrieve safe data. Additionally AllocHGlobal is happening here 
        ///                      so no need to demand permissions
        /// 
        [SecurityCritical,SecurityTreatAsSafe]
        private void FromRawBytes(byte[] data, int dataLength)  // Note: often the data buffer is larger than the actual data in it. 
        {
            // Technically, we should only compute our hash on the data in the buffer that is valid. 
            // However, it shouldn't really matter - the rest of the buffer is cleared when the 
            // managed array is allocated.  And changing this method requires updating asmmeta and
            // such, which we may not want to do for an SP fix. 
            Crc32Helper crc32 = new Crc32Helper();
            crc32.ComputeCrc32(data);
            _profileHash = crc32.Crc32Value;
 
            profileStruct profileStruct;
            IntPtr pColorSpaceFamily = IntPtr.Zero; 
            IntPtr pNumChannels = IntPtr.Zero; 
            profileStruct.dwType = (UInt32)ICMConstants.PROFILE_MEMBUFFER;
            int ndataLength = dataLength; 
            profileStruct.cbDataSize = (uint)ndataLength;

            IntPtr pProfile = IntPtr.Zero;
            IntPtr pHeader = IntPtr.Zero; 

            try 
            { 
                profileStruct.pProfileData = Marshal.AllocHGlobal(ndataLength);
                Marshal.Copy(data, 0, profileStruct.pProfileData, ndataLength); 
                pProfile = Marshal.AllocHGlobal(sizeOfProfile());
                Marshal.StructureToPtr(profileStruct, pProfile, true);

                Initialize(); 

                _colorContextHelper.OpenColorProfile(pProfile); 
 
                pHeader = Marshal.AllocHGlobal(256);
                _colorContextHelper.GetColorProfileHeader(pHeader); 

                _profileHeader = (ProfileHeaderStruct)Marshal.PtrToStructure(pHeader, typeof(ProfileHeaderStruct));
            }
            finally 
            {
                Marshal.FreeHGlobal(pProfile); 
                pProfile = IntPtr.Zero; 
                Marshal.FreeHGlobal(pHeader);
                pHeader = IntPtr.Zero; 
            }

            if (profileStruct.pProfileData != IntPtr.Zero)
            { 
                Marshal.FreeHGlobal(profileStruct.pProfileData);
                profileStruct.pProfileData = IntPtr.Zero; 
            } 

            switch ((ICMConstants)_profileHeader.phDataColorSpace) 
            {
                case ICMConstants.XYZ:
                case ICMConstants.Lab:
                case ICMConstants.Luv: 
                case ICMConstants.YCbr:
                case ICMConstants.Yxy: 
                case ICMConstants.HSV: 
                case ICMConstants.HLS:
                case ICMConstants.CMY: 
                    _numChannels = 3;
                    _colorSpaceFamily = StandardColorSpace.Unknown;
                    break;
                case ICMConstants.RGB: 
                    _colorSpaceFamily = StandardColorSpace.Rgb;
                    _numChannels = 3; 
                    break; 
                case ICMConstants.GRAY:
                    _colorSpaceFamily = StandardColorSpace.Gray; 
                    _numChannels = 1;
                    break;
                case ICMConstants.CMYK:
                    _colorSpaceFamily = StandardColorSpace.Cmyk; 
                    _numChannels = 4;
                    break; 
                case ICMConstants._2CLR: 
                    _colorSpaceFamily = StandardColorSpace.Multichannel;
                    _numChannels = 2; 
                    break;
                case ICMConstants._3CLR:
                    _colorSpaceFamily = StandardColorSpace.Multichannel;
                    _numChannels = 3; 
                    break;
                case ICMConstants._4CLR: 
                    _colorSpaceFamily = StandardColorSpace.Multichannel; 
                    _numChannels = 4;
                    break; 
                case ICMConstants._5CLR:
                    _numChannels = 5;
                    _colorSpaceFamily = StandardColorSpace.Multichannel;
                    break; 
                case ICMConstants._6CLR:
                    _numChannels = 6; 
                    _colorSpaceFamily = StandardColorSpace.Multichannel; 
                    break;
                case ICMConstants._7CLR: 
                    _numChannels = 7;
                    _colorSpaceFamily = StandardColorSpace.Multichannel;
                    break;
                case ICMConstants._8CLR: 
                    _numChannels = 8;
                    _colorSpaceFamily = StandardColorSpace.Multichannel; 
                    break; 
                case ICMConstants._9CLR:
                    _numChannels = 9; 
                    _colorSpaceFamily = StandardColorSpace.Multichannel;
                    break;
                case ICMConstants.ACLR:
                    _numChannels = 10; 
                    _colorSpaceFamily = StandardColorSpace.Multichannel;
                    break; 
                case ICMConstants.BCLR: 
                    _numChannels = 11;
                    _colorSpaceFamily = StandardColorSpace.Multichannel; 
                    break;
                case ICMConstants.CCLR:
                    _numChannels = 12;
                    _colorSpaceFamily = StandardColorSpace.Multichannel; 
                    break;
                case ICMConstants.DCLR: 
                    _numChannels = 13; 
                    _colorSpaceFamily = StandardColorSpace.Multichannel;
                    break; 
                case ICMConstants.ECLR:
                    _numChannels = 14;
                    _colorSpaceFamily = StandardColorSpace.Multichannel;
                    break; 
                case ICMConstants.FCLR:
                    _numChannels = 15; 
                    _colorSpaceFamily = StandardColorSpace.Multichannel; 
                    break;
                default: 
                    _numChannels = 0;
                    _colorSpaceFamily = StandardColorSpace.Unknown;
                    break;
            } 
        }
 
        ///  
        /// SecurityCritical: This code calls critical code (unmanaged)
        /// SecurityTreatAsSafe: Calls to retrieve safe data. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private void GetColorContextHandlerFromProfileBytes(byte[] pProfileBytes, int nNumberofProfileBytes)
        { 
            IntPtr pBuffer = IntPtr.Zero;
 
            try 
            {
                using (FactoryMaker factoryMaker = new FactoryMaker()) 
                {
                    HRESULT.Check(UnsafeNativeMethods.WICCodec.CreateColorContext(factoryMaker.ImagingFactoryPtr, out _colorContextHandle));

                    pBuffer = Marshal.AllocHGlobal(nNumberofProfileBytes); 

                    Marshal.Copy(pProfileBytes, 0, pBuffer, nNumberofProfileBytes); 
 
                    HRESULT.Check(UnsafeNativeMethods.WICCodec.ColorContext_InitializeFromMemory(_colorContextHandle, pBuffer, (UInt32)nNumberofProfileBytes));
                } 

            }
            finally
            { 
                Marshal.FreeHGlobal(pBuffer);
                pBuffer = IntPtr.Zero; 
            } 
        }
 
        unsafe private int sizeOfProfile()
        {
            return (sizeof(profileStruct));
        } 

        ///  
        /// SecurityCritical: This code calls critical code (unmanaged) 
        /// 
        [SecurityCritical] 
        private void Initialize()
        {
            _colorContextHelper = new ColorContextHelper();
        } 

        #endregion 
 
        #region Private Fields
 
        internal struct profileStruct
        {
            public UInt32 dwType;             // profile type
            public IntPtr pProfileData;       // it is profile bytes buffer containing color profile profile 
                                              // we have our own copy instead of retain to the unmanaged code
            public UInt32 cbDataSize;         // size of profile data 
        }; 

        ///  
        /// SecurityCritical: This comes out of an elevation needs to be critical and tracked.
        /// 
        [SecurityCritical]
        private ColorContextHelper _colorContextHelper; 

        private StandardColorSpace _colorSpaceFamily; 
 
        private int _numChannels;
 
        /// 
        /// SecurityCritical: May contain sensitive path information like %WINDIR%
        /// 
        private SecurityCriticalData _profileUri; 

        ///  
        /// SecurityCritical: Determines whether or not _profileUri contains sensitive data 
        /// that we need to demand access to
        ///  
        private SecurityCriticalDataForSet _isProfileUriNotFromUser;

        private struct ProfileHeaderStruct
        { 
            public uint phSize;             // profile size in bytes
            public uint phCMMType;          // CMM for this profile 
            public uint phVersion;          // profile format version number 
            public uint phClass;            // type of profile
            public uint phDataColorSpace;   // color space of data 
            public uint phConnectionSpace;  // PCS
            public uint phDateTime_0;       // date profile was created
            public uint phDateTime_1;       // date profile was created
            public uint phDateTime_2;       // date profile was created 
            public uint phSignature;        // magic number
            public uint phPlatform;         // primary platform 
            public uint phProfileFlags;     // various bit settings 
            public uint phManufacturer;     // device manufacturer
            public uint phModel;            // device model number 
            public uint phAttributes_0;     // device attributes
            public uint phAttributes_1;     // device attributes
            public uint phRenderingIntent;  // rendering intent
            public uint phIlluminant_0;     // profile illuminant 
            public uint phIlluminant_1;     // profile illuminant
            public uint phIlluminant_2;     // profile illuminant 
            public uint phCreator;          // profile creator 
            public IntPtr phReserved;       // reserved for future use
        }; 

        private UInt32 _profileHash;

        private ProfileHeaderStruct _profileHeader; 

        ///  
        /// SecurityCritical: Unmanaged ColorContext handle 
        /// 
        [SecurityCritical] 
        private SafeMILHandle _colorContextHandle;

        private const int _bufferSizeIncrement = 1024 * 1024;  // 1 Mb
 
        private const int _maximumColorContextLength = _bufferSizeIncrement * 32; // 32 Mb
 
        private static ICMConstants[] _colorTypeFromChannels = 
            new ICMConstants[9] {
                ICMConstants.COLORTYPE_UNDEFINED, 
                ICMConstants.COLORTYPE_UNDEFINED,
                ICMConstants.COLORTYPE_UNDEFINED,
                ICMConstants.COLOR_3_CHANNEL,
                ICMConstants.COLOR_CMYK, 
                ICMConstants.COLOR_5_CHANNEL,
                ICMConstants.COLOR_6_CHANNEL, 
                ICMConstants.COLOR_7_CHANNEL, 
                ICMConstants.COLOR_8_CHANNEL
                }; 

        private static string _colorProfileResources = "ColorProfiles";

        private static string _sRGBProfileName = "sRGB_icm"; 

        internal enum StandardColorSpace : int 
        { 
            Unknown = 0,
            Srgb = 1, 
            ScRgb = 2,
            Rgb = 3,
            Cmyk = 4,
            Gray = 6, 
            Multichannel = 7
        } 
 
        private enum ICMConstants : uint
        { 
            PROFILE_MEMBUFFER = 2,

            COLORTYPE_UNDEFINED = 0xFF,
            COLORTYPE_RGB       = 2, 

            COLOR_3_CHANNEL = 6, 
            COLOR_CMYK      = 7, 
            COLOR_5_CHANNEL = 8,
            COLOR_6_CHANNEL = 9, 
            COLOR_7_CHANNEL = 10,
            COLOR_8_CHANNEL = 11,

            sRGB  = 0x73524742, 
            XYZ   = 0x58595A20,
            Lab   = 0x4C616220, 
            Luv   = 0x4C757620, 
            YCbr  = 0x59436272,
            Yxy   = 0x59787920, 
            HSV   = 0x48535620,
            HLS   = 0x484C5320,
            CMY   = 0x434D5920,
            RGB   = 0x52474220, 
            GRAY  = 0x47524159,
            CMYK  = 0x434D594B, 
            _2CLR = 0x32434C52, 
            _3CLR = 0x33434C52,
            _4CLR = 0x34434C52, 
            _5CLR = 0x35434C52,
            _6CLR = 0x36434C52,
            _7CLR = 0x37434C52,
            _8CLR = 0x38434C52, 
            _9CLR = 0x39434C52,
            ACLR  = 0x41434C52, 
            BCLR  = 0x42434C52, 
            CCLR  = 0x43434C52,
            DCLR  = 0x44434C52, 
            ECLR  = 0x45434C52,
            FCLR  = 0x46434C52
        }
 
        #endregion
    } 
} 

 


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

Link Menu

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