Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Core / CSharp / System / Windows / Media / ColorContext.cs / 2 / 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

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- WebResponse.cs
- CharEnumerator.cs
- DataGridViewCheckBoxCell.cs
- XmlSchemaComplexContent.cs
- XmlSerializationReader.cs
- webproxy.cs
- SmiContextFactory.cs
- LocalizedNameDescriptionPair.cs
- StylusCaptureWithinProperty.cs
- BuildManager.cs
- CuspData.cs
- CompositeControl.cs
- TdsParserStateObject.cs
- SystemUdpStatistics.cs
- ComponentGlyph.cs
- ParameterCollection.cs
- FeatureSupport.cs
- _SecureChannel.cs
- ModuleBuilder.cs
- BackgroundWorker.cs
- XmlObjectSerializerReadContextComplex.cs
- UserPreferenceChangedEventArgs.cs
- TypeProvider.cs
- CompilerTypeWithParams.cs
- FrameworkContentElement.cs
- MappingException.cs
- ProfileElement.cs
- WebServiceData.cs
- AttachmentService.cs
- ConcurrencyMode.cs
- BlobPersonalizationState.cs
- PerformanceCounters.cs
- Attribute.cs
- MSAAEventDispatcher.cs
- ActiveDocumentEvent.cs
- BypassElement.cs
- ListView.cs
- _ServiceNameStore.cs
- TextBox.cs
- SemanticBasicElement.cs
- TextDecorationCollection.cs
- XmlReturnReader.cs
- HttpWebResponse.cs
- TypeDescriptionProvider.cs
- SiteMapNodeCollection.cs
- Configuration.cs
- AuthenticationModuleElement.cs
- SessionPageStateSection.cs
- DefaultAsyncDataDispatcher.cs
- SqlUdtInfo.cs
- InstancePersistence.cs
- BitmapDecoder.cs
- SrgsGrammar.cs
- HtmlHead.cs
- ScrollItemPattern.cs
- ViewPort3D.cs
- _CookieModule.cs
- TypeExtensionSerializer.cs
- PrintPreviewGraphics.cs
- Effect.cs
- MemoryRecordBuffer.cs
- ReflectionTypeLoadException.cs
- ContentTypeSettingDispatchMessageFormatter.cs
- ComponentDispatcherThread.cs
- AutoGeneratedField.cs
- BaseProcessor.cs
- MouseEvent.cs
- URL.cs
- Expression.cs
- ComponentResourceManager.cs
- RootBrowserWindowAutomationPeer.cs
- UnsafeMethods.cs
- TextContainer.cs
- SHA1.cs
- ShowExpandedMultiValueConverter.cs
- InheritablePropertyChangeInfo.cs
- DeviceFilterEditorDialog.cs
- DmlSqlGenerator.cs
- TreeView.cs
- ListViewDeleteEventArgs.cs
- TypefaceCollection.cs
- GPRECT.cs
- UpdateException.cs
- Path.cs
- CacheVirtualItemsEvent.cs
- SafeRightsManagementHandle.cs
- ObjectStorage.cs
- FirstMatchCodeGroup.cs
- DetailsViewUpdateEventArgs.cs
- OverflowException.cs
- TextAdaptor.cs
- Empty.cs
- FontStretchConverter.cs
- SubMenuStyleCollection.cs
- FilterException.cs
- UserControl.cs
- XmlSchemaSearchPattern.cs
- AuthenticationService.cs
- InProcStateClientManager.cs
- OperatorExpressions.cs