SystemResources.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Framework / System / Windows / SystemResources.cs / 1 / SystemResources.cs

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

using System; 
using System.Diagnostics; 
using System.IO;
using System.Reflection; 
using System.Resources;
using System.Runtime.InteropServices;
using System.Collections;
using System.Collections.Generic; 
using System.Globalization;
using System.Security; 
using System.Security.Permissions; 
using System.Windows.Threading;
using System.Text; 
using MS.Utility;
using System.Windows.Controls.Primitives;
using System.Windows.Markup;
using System.Windows.Documents; 
using System.Windows.Media;
using System.Windows.Input; 
using System.Windows.Resources; 
using MS.Win32;
using MS.Internal; 
using MS.Internal.Ink;
using MS.Internal.PresentationFramework;                   // SafeSecurityHelper

// Disable pragma warnings to enable PREsharp pragmas 
#pragma warning disable 1634, 1691
 
namespace System.Windows 
{
    ///  
    ///     SystemResources loads system theme data into the system resources collection.
    /// 
    internal static class SystemResources
    { 
        // ------------------------------------------------
        // 
        // Methods 
        //
        // ------------------------------------------------ 

        #region Methods

        ///  
        ///     Returns a resource for the given key type from the system resources collection.
        ///  
        /// The resource id to search for. 
        /// The resource if it exists, null otherwise.
        //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647 
        internal static object FindThemeStyle(DependencyObjectType key)
        {
            // Find a cached theme style
            object resource = _themeStyleCache[key]; 
            if (resource != null)
            { 
                // Found a cached value 
                if (resource == _specialNull)
                { 
                    // We cached a null, set it to a real null
                    return null; // Null resource found
                }
 
                return resource;
            } 
 
            // Find the resource from the system resources collection
            resource = FindResourceInternal(key.SystemType); 

            // The above read operation was lock free. Writing
            // to the cache will need a lock though
            lock (ThemeDictionaryLock) 
            {
                if (resource != null) 
                { 
                    // Cache the value
                    _themeStyleCache[key] = resource; 
                }
                else
                {
                    // Record nulls so we don't bother doing lookups for them later 
                    // Any theme changes will clear these values
                    _themeStyleCache[key] = _specialNull; 
                } 
            }
 
            return resource;
        }

        ///  
        ///     Returns a resource of the given name from the system resources collection.
        ///  
        /// The resource id to search for. 
        /// The resource if it exists, null otherwise.
        //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647 
        internal static object FindResourceInternal(object key)
        {
            // Call Forwarded
            return FindResourceInternal(key, false /*allowDeferredResourceReference*/, false /*mustReturnDeferredResourceReference*/); 
        }
 
        internal static object FindResourceInternal(object key, bool allowDeferredResourceReference, bool mustReturnDeferredResourceReference) 
        {
            // Ensure that resource changes on this thread can be heard and handled 
            EnsureResourceChangeListener();

            object resource = null;
            Type typeKey = null; 
            ResourceKey resourceKey = null;
 
            bool isTraceEnabled = EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose); 

            // System resource keys can only be of type Type or of type ResourceKey 
            typeKey = key as Type;
            resourceKey = (typeKey == null) ? (key as ResourceKey) : null;

            if (isTraceEnabled) 
            {
                EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.RESOURCEFINDGUID), 
                                                    MS.Utility.EventType.StartEvent, 
                                                    (key == null) ? "null" : key.ToString());
            } 


            if ((typeKey == null) && (resourceKey == null))
            { 
                // Not a valid key
                if (isTraceEnabled) 
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.RESOURCEFINDGUID), MS.Utility.EventType.EndEvent);
                } 
                return null;
            }

            // Check if the value was already cached 
            if (!FindCachedResource(key, ref resource, mustReturnDeferredResourceReference))
            { 
                // Cache miss, do a lookup 
                if (isTraceEnabled)
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.RESOURCECACHEMISSGUID), MS.Utility.EventType.Info);
                }

                lock (ThemeDictionaryLock) 
                {
                    bool canCache = true; 
                    SystemResourceKey sysKey = (resourceKey != null) ? resourceKey as SystemResourceKey : null; 
                    if (sysKey != null)
                    { 
                        // Check the list of system metrics
                        if (!mustReturnDeferredResourceReference)
                        {
                            resource = sysKey.Resource; 
                        }
                        else 
                        { 
                            resource = new DeferredResourceReferenceHolder(sysKey, sysKey.Resource);
                        } 
                        if (isTraceEnabled)
                        {
                            EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.RESOURCESTOCKGUID),
                                                                 MS.Utility.EventType.Info, 
                                                                 sysKey.ToString());
                        } 
                    } 
                    else
                    { 
                        // Do a dictionary lookup
                        resource = FindDictionaryResource(key, typeKey, resourceKey, isTraceEnabled, allowDeferredResourceReference, mustReturnDeferredResourceReference, out canCache);
                    }
 
                    if ((canCache && !allowDeferredResourceReference) || resource == null)
                    { 
                        // Cache the resource 
                        CacheResource(key, resource, isTraceEnabled);
                    } 
                }
            }

            if (isTraceEnabled) 
            {
                EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.RESOURCEFINDGUID), MS.Utility.EventType.EndEvent); 
            } 

            return resource; 
        }

        #endregion
 
        // ------------------------------------------------
        // 
        // Implementation 
        //
        // ------------------------------------------------ 

        #region Implementation

        //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647 
        internal static void CacheResource(object key, object resource, bool isTraceEnabled)
        { 
            // Thread safety handled by FindResourceInternal. Be sure to have locked _resourceCache.SyncRoot. 

            if (resource != null) 
            {
                // Cache the value
                _resourceCache[key] = resource;
 
                if (isTraceEnabled)
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.RESOURCECACHEVALUEGUID), MS.Utility.EventType.Info); 
                }
            } 
            else
            {
                // Record nulls so we don't bother doing lookups for them later
                // Any theme changes will clear these values 
                _resourceCache[key] = _specialNull;
 
                if (isTraceEnabled) 
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.RESOURCECACHENULLGUID), MS.Utility.EventType.Info); 
                }
            }
        }
 
        #region Resource Value Lookup
 
        private static bool FindCachedResource(object key, ref object resource, bool mustReturnDeferredResourceReference) 
        {
            // reading the cache is lock free 

            resource = _resourceCache[key];
            bool found = (resource != null);
 
            if (resource == _specialNull)
            { 
                // We cached a null, set it to a real null 
                resource = null;
            } 
            else
            {
                DispatcherObject dispatcherObject = resource as DispatcherObject;
                if (dispatcherObject != null) 
                {
                    // The current thread may not have access to this object. 
                    dispatcherObject.VerifyAccess(); 
                }
            } 

            if (found && mustReturnDeferredResourceReference)
            {
                resource = new DeferredResourceReferenceHolder(key, resource); 
            }
 
            return found; 
        }
 
        /// 
        ///     Searches for a resource inside a ResourceDictionary.
        /// 
        /// The original key. 
        /// The key cast to Type.
        /// The key cast to ResourceKey. 
        /// Tracing on/off. 
        /// 
        ///     If this flag is true the resource will not actually be inflated from Baml. 
        ///     Instead we will return an instance of DeferredDictionaryReference which
        ///     can later be used to query the resource
        /// 
        ///  
        ///     If this method is true this method will always return a
        ///     DeferredThemeResourceReference instance which envelopes the underlying resource. 
        ///  
        /// Whether callers can cache the value.
        ///  
        private static object FindDictionaryResource(
            object      key,
            Type        typeKey,
            ResourceKey resourceKey, 
            bool        isTraceEnabled,
            bool        allowDeferredResourceReference, 
            bool        mustReturnDeferredResourceReference, 
            out bool    canCache)
        { 
            // Thread safety handled by FindResourceInternal. Be sure to have locked _resourceCache.SyncRoot.

            Debug.Assert(typeKey != null || resourceKey != null, "typeKey or resourceKey should be non-null");
 
            canCache = true;
            object resource = null; 
            Assembly assembly = (typeKey != null) ? typeKey.Assembly : resourceKey.Assembly; 

            if ((assembly == null) || IgnoreAssembly(assembly)) 
            {
                // Without an assembly, we can't figure out which dictionary to look at.
                // Also, ignore some common assemblies we know to not contain resources.
                return null; 
            }
 
            ResourceDictionaries dictionaries = EnsureDictionarySlot(assembly); 
            ResourceDictionary dictionary = dictionaries.LoadThemedDictionary(isTraceEnabled);
            if (dictionary != null) 
            {
                resource = LookupResourceInDictionary(dictionary, key, allowDeferredResourceReference, mustReturnDeferredResourceReference, out canCache);
            }
 
            if (resource == null)
            { 
                dictionary = dictionaries.LoadGenericDictionary(isTraceEnabled); 
                if (dictionary != null)
                { 
                    resource = LookupResourceInDictionary(dictionary, key, allowDeferredResourceReference, mustReturnDeferredResourceReference, out canCache);
                }
            }
 
            if (resource != null)
            { 
                // Resources coming out of the dictionary may need to be frozen 
                Freeze(resource);
            } 

            return resource;
        }
 
        /// 
        ///     Looks in the ResourceDictionary for the desired resource. 
        ///  
        /// The ResourceDictionary to look in.
        /// The key for the resource. 
        /// 
        ///     If this flag is true the resource will not actually be inflated from Baml.
        ///     Instead we will return an instance of DeferredDictionaryReference which
        ///     can later be used to query the resource 
        /// 
        ///  
        ///     If this method is true this method will always return a 
        ///     DeferredThemeResourceReference instance which envelopes the underlying resource.
        ///  
        /// Whether callers should cache the value.
        /// The resource if found and successfully loaded, null otherwise.
        private static object LookupResourceInDictionary(
            ResourceDictionary  dictionary, 
            object              key,
            bool                allowDeferredResourceReference, 
            bool                mustReturnDeferredResourceReference, 
            out bool            canCache)
        { 
            object resource = null;
            IsSystemResourcesParsing = true;

            try 
            {
                resource = dictionary.FetchResource(key, allowDeferredResourceReference, mustReturnDeferredResourceReference, out canCache); 
            } 
            finally
            { 
                IsSystemResourcesParsing = false;
            }

            return resource; 
        }
 
        ///  
        ///     Unbinds a Freezable from its Context.
        ///  
        /// The resource to freeze.
        private static void Freeze(object resource)
        {
            Freezable freezable = resource as Freezable; 
            if (freezable != null && !freezable.IsFrozen)
            { 
                freezable.Freeze(); 
            }
        } 

        #endregion

        #region Dictionary Loading 

        ///  
        ///     Returns the dictionary cache slot associated with the given assembly. 
        /// 
        /// The desired assembly 
        /// The cache slot.
        private static ResourceDictionaries EnsureDictionarySlot(Assembly assembly)
        {
            ResourceDictionaries dictionaries = null; 
            if (_dictionaries != null)
            { 
                _dictionaries.TryGetValue(assembly, out dictionaries); 
            }
            else 
            {
                // We will be caching data, create the cache
                _dictionaries = new Dictionary(1);
            } 

            if (dictionaries == null) 
            { 
                // Ensure the cache slot is created
                dictionaries = new ResourceDictionaries(assembly); 
                _dictionaries.Add(assembly, dictionaries);
            }

            return dictionaries; 
        }
 
        private static bool IgnoreAssembly(Assembly assembly) 
        {
            return (assembly == MsCorLib) || (assembly == PresentationCore) || (assembly == WindowsBase); 
        }

        private static Assembly MsCorLib
        { 
            get
            { 
                if (_mscorlib == null) 
                {
                    _mscorlib = typeof(string).Assembly; 
                }

                return _mscorlib;
            } 
        }
 
        private static Assembly PresentationFramework 
        {
            get 
            {
                if (_presentationFramework == null)
                {
                    _presentationFramework = typeof(FrameworkElement).Assembly; 
                }
 
                return _presentationFramework; 
            }
        } 

        private static Assembly PresentationCore
        {
            get 
            {
                if (_presentationCore == null) 
                { 
                    _presentationCore = typeof(UIElement).Assembly;
                } 

                return _presentationCore;
            }
        } 

        private static Assembly WindowsBase 
        { 
            get
            { 
                if (_windowsBase == null)
                {
                    _windowsBase = typeof(DependencyObject).Assembly;
                } 

                return _windowsBase; 
            } 
        }
 
        /// 
        ///     Loads and caches the generic and themed resource dictionaries for an assembly.
        /// 
        internal class ResourceDictionaries 
        {
            ///  
            ///     Creates an instance of this class. 
            /// 
            /// The assembly that this class represents. 
            internal ResourceDictionaries(Assembly assembly)
            {
                _assembly = assembly;
                if (assembly == PresentationFramework) 
                {
                    // Since we know all the information about PresentationFramework in advance, 
                    // we can pre-initialize that data. 
                    _assemblyName = PresentationFrameworkName;
 
                    // There is no generic dictionary
                    _genericDictionary = null;
                    _genericLoaded = true;
                    _genericLocation = ResourceDictionaryLocation.None; 

                    // Themed dictionaries are all external 
                    _themedLocation = ResourceDictionaryLocation.ExternalAssembly; 
                    _locationsLoaded = true;
                } 
                else
                {
                    _assemblyName = SafeSecurityHelper.GetAssemblyPartialName(assembly);
                } 
            }
 
            ///  
            ///     Resets the themed dictionaries. This is used when the theme changes.
            ///  
            internal void ClearThemedDictionary()
            {
                _themedLoaded = false;
                _themedDictionary = null; 
            }
 
            ///  
            ///     Returns the theme dictionary associated with this assembly.
            ///  
            /// Whether debug tracing is enabled.
            /// The dictionary if loaded, otherwise null.
            internal ResourceDictionary LoadThemedDictionary(bool isTraceEnabled)
            { 
                if (!_themedLoaded)
                { 
                    LoadDictionaryLocations(); 

                    if (_preventReEnter || (_themedLocation == ResourceDictionaryLocation.None)) 
                    {
                        // We are already in the middle of parsing this resource dictionary, avoid infinite loops.
                        // OR, there are no themed resources.
                        return null; 
                    }
 
                    IsSystemResourcesParsing = true; 
                    _preventReEnter = true;
                    try 
                    {
                        ResourceDictionary dictionary = null;

                        // Get the assembly to look inside for resources. 
                        Assembly assembly;
                        string assemblyName; 
                        bool external = (_themedLocation == ResourceDictionaryLocation.ExternalAssembly); 
                        if (external)
                        { 
                            LoadExternalAssembly(false /* classic */, false /* generic */, out assembly, out assemblyName);
                        }
                        else
                        { 
                            assembly = _assembly;
                            assemblyName = _assemblyName; 
                        } 

                        if (assembly != null) 
                        {
                            dictionary = LoadDictionary(assembly, assemblyName, ThemedResourceName, isTraceEnabled);
                            if ((dictionary == null) && !external)
                            { 
                                // Themed resources should have been inside the source assembly, but failed to load.
                                // Try falling back to external in case this is a theme that shipped later. 
                                LoadExternalAssembly(false /* classic */, false /* generic */, out assembly, out assemblyName); 
                                if (assembly != null)
                                { 
                                    dictionary = LoadDictionary(assembly, assemblyName, ThemedResourceName, isTraceEnabled);
                                }
                            }
                        } 

                        if ((dictionary == null) && UxThemeWrapper.IsActive) 
                        { 
                            // If a non-classic dictionary failed to load, then try to load classic.
                            if (external) 
                            {
                                LoadExternalAssembly(true /* classic */, false /* generic */, out assembly, out assemblyName);
                            }
                            else 
                            {
                                assembly = _assembly; 
                                assemblyName = _assemblyName; 
                            }
 
                            if (assembly != null)
                            {
                                dictionary = LoadDictionary(assembly, assemblyName, ClassicResourceName, isTraceEnabled);
                            } 
                        }
 
                        _themedDictionary = dictionary; 
                        _themedLoaded = true;
                    } 
                    finally
                    {
                        _preventReEnter = false;
                        IsSystemResourcesParsing = false; 
                    }
                } 
 
                return _themedDictionary;
            } 

            /// 
            ///     Returns the generic dictionary associated with this assembly.
            ///  
            /// Whether debug tracing is enabled.
            /// The dictionary if loaded, otherwise null. 
            internal ResourceDictionary LoadGenericDictionary(bool isTraceEnabled) 
            {
                if (!_genericLoaded) 
                {
                    LoadDictionaryLocations();

                    if (_preventReEnter || (_genericLocation == ResourceDictionaryLocation.None)) 
                    {
                        // We are already in the middle of parsing this resource dictionary, avoid infinite loops. 
                        return null; 
                    }
 
                    IsSystemResourcesParsing = true;
                    _preventReEnter = true;
                    try
                    { 
                        ResourceDictionary dictionary = null;
 
                        // Get the assembly to look inside 
                        Assembly assembly;
                        string assemblyName; 
                        if (_genericLocation == ResourceDictionaryLocation.ExternalAssembly)
                        {
                            LoadExternalAssembly(false /* classic */, true /* generic */, out assembly, out assemblyName);
                        } 
                        else
                        { 
                            assembly = _assembly; 
                            assemblyName = _assemblyName;
                        } 

                        if (assembly != null)
                        {
                            dictionary = LoadDictionary(assembly, assemblyName, GenericResourceName, isTraceEnabled); 
                        }
 
                        _genericDictionary = dictionary; 
                        _genericLoaded = true;
                    } 
                    finally
                    {
                        _preventReEnter = false;
                        IsSystemResourcesParsing = false; 
                    }
                } 
 
                return _genericDictionary;
            } 

            /// 
            ///     Loads the assembly attribute indicating where dictionaries are stored.
            ///  
            private void LoadDictionaryLocations()
            { 
                if (!_locationsLoaded) 
                {
                    ThemeInfoAttribute locations = ThemeInfoAttribute.FromAssembly(_assembly); 
                    if (locations != null)
                    {
                        _themedLocation = locations.ThemeDictionaryLocation;
                        _genericLocation = locations.GenericDictionaryLocation; 
                    }
                    else 
                    { 
                        _themedLocation = ResourceDictionaryLocation.None;
                        _genericLocation = ResourceDictionaryLocation.None; 
                    }
                    _locationsLoaded = true;
                }
            } 

            ///  
            ///     Loads an associated theme assembly based on a main assembly. 
            /// 
            private void LoadExternalAssembly(bool classic, bool generic, out Assembly assembly, out string assemblyName) 
            {
                StringBuilder sb = new StringBuilder(_assemblyName.Length + 10);

                sb.Append(_assemblyName); 
                sb.Append(".");
 
                if (generic) 
                {
                    sb.Append("generic"); 
                }
                else if (classic)
                {
                    sb.Append("classic"); 
                }
                else 
                { 
                    sb.Append(UxThemeWrapper.ThemeName);
                } 

                assemblyName = sb.ToString();
                string fullName = SafeSecurityHelper.GetFullAssemblyNameFromPartialName(_assembly, assemblyName);
 
                assembly = null;
                try 
                { 
                    assembly = Assembly.Load(fullName);
                } 
                // There is no Assembly.Exists API to determine if an Assembly exists.
                // There is also no way to determine if an Assembly's format is good prior to loading it.
                // So, the exception must be caught. assembly will continue to be null and returned.
#pragma warning disable 6502 
                catch (FileNotFoundException)
                { 
                } 
                catch (BadImageFormatException)
                { 
                }
#pragma warning restore 6502
            }
 
            /// 
            ///     The string to use as the key to load the .NET resource stream that contains themed resources. 
            ///  
            internal static string ThemedResourceName
            { 
                get
                {
                    if (_themedResourceName == null)
                    { 
                        if (UxThemeWrapper.IsActive)
                        { 
                            _themedResourceName = "themes/" + UxThemeWrapper.ThemeName.ToLowerInvariant() + "." + UxThemeWrapper.ThemeColor.ToLowerInvariant(); 
                        }
                        else 
                        {
                            _themedResourceName = ClassicResourceName;
                        }
                    } 

                    return _themedResourceName; 
                } 
            }
 
            /// 
            ///     Loads a ResourceDictionary from within an assembly's .NET resource store.
            /// 
            /// The owning assembly. 
            /// The name of the owning assembly.
            /// The name of the desired theme resource. 
            /// Whether tracing is enabled. 
            /// The dictionary if found and loaded successfully, null otherwise.
            private ResourceDictionary LoadDictionary(Assembly assembly, string assemblyName, string resourceName, bool isTraceEnabled) 
            {
                ResourceDictionary dictionary = null;

                // Create the resource manager that will load the byte array 
                ResourceManager rm = new ResourceManager(assemblyName + ".g", assembly);
 
                resourceName = resourceName + ".baml"; 
                // Load the resource stream
                Stream stream = null; 
                try
                {
                    stream = rm.GetStream(resourceName, CultureInfo.CurrentUICulture);
                } 
                // There is no ResourceManager.HasManifest in order to detect this case before an exception is thrown.
                // Likewise, there is no way to know if loading a resource will fail prior to loading it. 
                // So, the exceptions must be caught. stream will continue to be null and handled accordingly later. 
#pragma warning disable 6502
 
                catch (MissingManifestResourceException)
                {
                    // No usable resources in the assembly
                } 
#if !DEBUG
                catch (InvalidOperationException) 
                { 
                    // Object not stored correctly
                } 
#endif

#pragma warning restore 6502
 
                if (stream != null)
                { 
                    ParserContext pc = new ParserContext(); 

                    // The stream is actually owned by the theme engine and will remain open 
                    // as long as the loading process is alive. So this can be re-used by the
                    // parser when loading defered content like this dictionary instead of creating
                    // a new memory buffer.
                    pc.OwnsBamlStream = true; 

                    dictionary = (ResourceDictionary)XamlReader.LoadBaml( 
                        stream,                             // Stream input 
                        pc,                                 // Parser Context
                        null,                               // Owner element 
                        false);                             // Do not Close the stream

                    if (isTraceEnabled && (dictionary != null))
                    { 
                        EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.RESOURCEBAMLASSEMBLYGUID),
                                                             MS.Utility.EventType.Info, 
                                                             assemblyName); 
                    }
                } 

                return dictionary;
            }
 
            internal static void OnThemeChanged()
            { 
                _themedResourceName = null; 
            }
 
            private ResourceDictionary _genericDictionary;
            private ResourceDictionary _themedDictionary;
            private bool _genericLoaded = false;
            private bool _themedLoaded = false; 
            private bool _preventReEnter = false;
            private bool _locationsLoaded = false; 
            private string _assemblyName; 
            private Assembly _assembly;
            private ResourceDictionaryLocation _genericLocation; 
            private ResourceDictionaryLocation _themedLocation;

            private static string _themedResourceName;
        } 

        #endregion 
 
        #region Value Changes
 
        // The hwndNotify is referenced by the _hwndNotify static field, but
        // PreSharp will think that the hwndNotify is local and should be disposed.
#pragma warning disable 6518
 
        ///
        ///     Critical - Creates an HwndWrapper and adds a hook. 
        ///     TreatAsSafe: The _hwndNotify window is critical and this function is safe to call 
        ///
        [SecurityCritical,SecurityTreatAsSafe] 
        private static void EnsureResourceChangeListener()
        {
            // Create a new notify window if we haven't already created one for this thread.
            if (_hwndNotify == null) 
            {
                // Create a top-level, invisible window so we can get the WM_THEMECHANGE notification. 
                HwndWrapper hwndNotify; 
                hwndNotify = new HwndWrapper(0, NativeMethods.WS_POPUP, 0, 0, 0, 0, 0, "SystemResourceNotifyWindow", IntPtr.Zero, null);
                _hwndNotify = new SecurityCriticalDataClass(hwndNotify); 
                _hwndNotify.Value.Dispatcher.ShutdownFinished += OnShutdownFinished;
                _hwndNotifyHook = new HwndWrapperHook(SystemThemeFilterMessage);
                _hwndNotify.Value.AddHook(_hwndNotifyHook);
            } 
        }
 
        /// 
        ///     Critical - Calls dispose on the critical hwnd wrapper.
        ///     TreatAsSafe: It is safe to dispose the wrapper 
        ///
        [SecurityCritical, SecurityTreatAsSafe]
        private static void OnShutdownFinished(object sender, EventArgs args)
        { 
            if (_hwndNotify != null)
                _hwndNotify.Value.Dispose(); 
 
            _hwndNotifyHook = null;
            _hwndNotify = null; 
        }

#pragma warning restore 6518
 
        private static void OnThemeChanged()
        { 
            ResourceDictionaries.OnThemeChanged(); 
            UxThemeWrapper.OnThemeChanged();
            ThemeDictionaryExtension.OnThemeChanged(); 

            lock (ThemeDictionaryLock)
            {
                // Clear the resource cache 
                _resourceCache.Clear();
 
                // Clear the themeStyleCache 
                _themeStyleCache.Clear();
 
                // Clear the themed dictionaries
                if (_dictionaries != null)
                {
                    foreach (ResourceDictionaries dictionaries in _dictionaries.Values) 
                    {
                        dictionaries.ClearThemedDictionary(); 
                    } 
                }
            } 
        }

        private static void OnSystemValueChanged()
        { 
            lock (ThemeDictionaryLock)
            { 
                // Collect the list of keys for the values that will need to be removed 
                // Note: We don't immediately remove them because the Key list is not
                // static. 

                List keys = new List();

                foreach (object key in _resourceCache.Keys) 
                {
                    SystemResourceKey resKey = key as SystemResourceKey; 
                    if (resKey != null) 
                    {
                        keys.Add(resKey); 
                    }
                }

                // Remove the values 

                int count = keys.Count; 
                for (int i = 0; i < count; i++) 
                {
                    _resourceCache.Remove(keys[i]); 
                }
            }
        }
 
        private static object InvalidateTreeResources(Object args)
        { 
            object[] argsArray = (object[])args; 
            PresentationSource source = (PresentationSource)argsArray[0];
            if (!source.IsDisposed) 
            {
                FrameworkElement fe = source.RootVisual as FrameworkElement;
                if (fe != null)
                { 
                    bool isSysColorsOrSettingsChange = (bool)argsArray[1];
                    if (isSysColorsOrSettingsChange) 
                    { 
                        TreeWalkHelper.InvalidateOnResourcesChange(fe, null, ResourcesChangeInfo.SysColorsOrSettingsChangeInfo);
                    } 
                    else
                    {
                        TreeWalkHelper.InvalidateOnResourcesChange(fe, null, ResourcesChangeInfo.ThemeChangeInfo);
                    } 

                    System.Windows.Input.KeyboardNavigation.AlwaysShowFocusVisual = SystemParameters.KeyboardCues; 
                    fe.CoerceValue(System.Windows.Input.KeyboardNavigation.ShowKeyboardCuesProperty); 

                    SystemResourcesAreChanging = true; 
                    // Update FontFamily properties on root elements
                    fe.CoerceValue(TextElement.FontFamilyProperty);
                    fe.CoerceValue(TextElement.FontSizeProperty);
                    fe.CoerceValue(TextElement.FontStyleProperty); 
                    fe.CoerceValue(TextElement.FontWeightProperty);
                    SystemResourcesAreChanging = false; 
 
                    PopupRoot popupRoot = fe as PopupRoot;
                    if (popupRoot != null && popupRoot.Parent != null) 
                    {
                        popupRoot.Parent.CoerceValue(Popup.HasDropShadowProperty);
                    }
                } 
            }
 
            return null; 
        }
 
        /// 
        /// This method calls into PresentationCore internally to update Tabelt devices when the system settings change.
        /// 
        ///  
        /// 
        ///  
        ///  
        ///     Critical - Accesses the critical data.
        ///                 _hwndNotify 
        /// 
        [SecurityCritical]
        private static void InvalidateTabletDevices(int msg, IntPtr wParam, IntPtr lParam)
        { 
            if ( _hwndNotify != null )
            { 
                Dispatcher dispatcher = _hwndNotify.Value.Dispatcher; 
                if ( dispatcher != null && dispatcher.InputManager != null )
                { 
                    ((InputManager)dispatcher.InputManager).StylusLogic.HandleMessage(msg, wParam, lParam);
                }
            }
        } 

        /// 
        ///     Critical - calls CriticalCurrentSources. 
        ///     TreatAsSafe - invalidation of resources considered ok.
        ///                   Net effect is an invalidation of tree and reload of BAML from theme files. 
        ///                   Worse that could happen is a DOS attack within the app.
        ///
        [SecurityCritical, SecurityTreatAsSafe ]
        private static void InvalidateResources(bool isSysColorsOrSettingsChange) 
        {
            SystemResourcesHaveChanged = true; 
 
            Dispatcher dispatcher = isSysColorsOrSettingsChange ? null : Dispatcher.FromThread(System.Threading.Thread.CurrentThread);
            if (dispatcher != null || isSysColorsOrSettingsChange) 
            {
                foreach (PresentationSource source in PresentationSource.CriticalCurrentSources)
                {
                    if (!source.IsDisposed && (isSysColorsOrSettingsChange || (source.Dispatcher == dispatcher))) 
                    {
                        source.Dispatcher.BeginInvoke(DispatcherPriority.Normal, 
                                                      new DispatcherOperationCallback(InvalidateTreeResources), 
                                                      new object[]{source, isSysColorsOrSettingsChange});
                    } 
                }
            }
        }
        ///  
        ///     Critical: This code calls into PeekMessage and can be used to spoof theme change messages
        ///     TreatAsSafe:The call to PeekMessage is safe and no information is exposed. In the case of the 
        ///     messages handled in this function, no data is passed in or out, the only form of attack possible 
        ///     here is DOS by excessive calls to this.
        ///  
        [SecurityCritical,SecurityTreatAsSafe]
        private static IntPtr SystemThemeFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            switch (msg) 
            {
                case NativeMethods.WM_DEVICECHANGE: 
                    InvalidateTabletDevices(msg, wParam, lParam); 

                    // If there was an invalidation made to a Mouse metric, 
                    // then resource references need to be invalidated.
                    if (SystemParameters.InvalidateDeviceDependentCache())
                    {
                        OnSystemValueChanged(); 
                        InvalidateResources(true); // Invalidate all resource since this should happen only once
                    } 
                    break; 

                case NativeMethods.WM_DISPLAYCHANGE: 
                    InvalidateTabletDevices(msg, wParam, lParam);

                    // If there was an invalidation made to a Display metric,
                    // then resource references need to be invalidated. 
                    if (SystemParameters.InvalidateDisplayDependentCache())
                    { 
                        OnSystemValueChanged(); 
                        InvalidateResources(true); // Invalidate all resource since this should happen only once
                    } 
                    break;

                case NativeMethods.WM_POWERBROADCAST:
                    // If there was an invalidation made to a Power Setting, 
                    // then resource references need to be invalidated.
                    if (NativeMethods.IntPtrToInt32(wParam) == NativeMethods.PBT_APMPOWERSTATUSCHANGE && 
                        SystemParameters.InvalidatePowerDependentCache()) 
                    {
                        OnSystemValueChanged(); 
                        InvalidateResources(true); // Invalidate all resource since this should happen only once
                    }
                    break;
 
                case NativeMethods.WM_THEMECHANGED:
                    bool usingSendMessage = SafeNativeMethods.InSendMessage(); 
                    if (!usingSendMessage) 
                    {
                        System.Windows.Interop.MSG m = new System.Windows.Interop.MSG(); 
                        bool moreMessagesPosted = UnsafeNativeMethods.PeekMessage(ref m, new HandleRef(null, hwnd), NativeMethods.WM_THEMECHANGED, NativeMethods.WM_THEMECHANGED, NativeMethods.PM_NOREMOVE);
                        if (!moreMessagesPosted)
                        {
                            SystemColors.InvalidateCache(); 
                            SystemParameters.InvalidateCache();
                            OnThemeChanged(); 
                            InvalidateResources(false); // Only invalidate this thread's resources, other threads will get a chance 
                        }
                    } 
                    break;

                case NativeMethods.WM_SYSCOLORCHANGE:
                    // If there was an invalidation made to a system color or brush, 
                    // then resource references need to be invalidated.
                    if (SystemColors.InvalidateCache()) 
                    { 
                        OnSystemValueChanged();
                        InvalidateResources(true); // Invalidate all resource since this should happen only once 
                    }
                    break;

                case NativeMethods.WM_SETTINGCHANGE: 
                    InvalidateTabletDevices(msg, wParam, lParam); // Update tablet device settings
 
                    // If there was an invalidation made to a system param or metric, 
                    // then resource references need to be invalidated.
                    if (SystemParameters.InvalidateCache((int)wParam)) 
                    {
                        OnSystemValueChanged();
                        InvalidateResources(true); // Invalidate all resource since this should happen only once
 
                        // NOTICE-2005/06/17-WAYNEZEN,
                        // We have to invoke the below method after InvalidateResources. 
                        // So the tablet ink HighContrastHelper can pick up the correct HighContrast setting. 
                        HighContrastHelper.OnSettingChanged();
                    } 
                    break;

                case NativeMethods.WM_TABLET_ADDED:
                    InvalidateTabletDevices(msg, wParam, lParam); 
                    break;
 
                case NativeMethods.WM_TABLET_REMOVED: 
                    InvalidateTabletDevices(msg, wParam, lParam);
                    break; 

            }

            return IntPtr.Zero ; 

        } 
 
        internal static bool ClearBitArray(BitArray cacheValid)
        { 
            bool changed = false;

            for (int i = 0; i < cacheValid.Count; i++)
            { 
                if (ClearSlot(cacheValid, i))
                { 
                    changed = true; 
                }
            } 

            return changed;
        }
 
        internal static bool ClearSlot(BitArray cacheValid, int slot)
        { 
            if (cacheValid[slot]) 
            {
                cacheValid[slot] = false; 
                return true;
            }

            return false; 
        }
 
        #endregion 

        // Flag the parser to create DeferredThemeReferences for thread safety 
        internal static bool IsSystemResourcesParsing
        {
            get
            { 
                return _parsing > 0;
            } 
            set 
            {
                if (value) 
                {
                    _parsing++;
                }
                else 
                {
                    _parsing--; 
                } 
            }
        } 

        // This is the lock used to protect access to the
        // theme dictionaries and the associated cache.
        internal static object ThemeDictionaryLock 
        {
            get { return _resourceCache.SyncRoot; } 
        } 

        #endregion 

        #region Data

        [ThreadStatic] private static int _parsing; 

        [ThreadStatic] private static SecurityCriticalDataClass _hwndNotify; 
        [ThreadStatic] [SecurityCritical] private static HwndWrapperHook _hwndNotifyHook; 

        private static Hashtable _resourceCache = new Hashtable(); 
        private static DTypeMap _themeStyleCache = new DTypeMap(100); // This is based upon the max DType.ID found in MSN scenario
        private static Dictionary _dictionaries;
        private static object _specialNull = new object();
 
        private const string GenericResourceName = "themes/generic";
        private const string ClassicResourceName = "themes/classic"; 
 
        private static Assembly _mscorlib;
        private static Assembly _presentationFramework; 
        private static Assembly _presentationCore;
        private static Assembly _windowsBase;
        internal const string PresentationFrameworkName = "PresentationFramework";
 
        // SystemResourcesHaveChanged indicates to FE that the font properties need to be coerced
        // when creating a new root element 
        internal static bool SystemResourcesHaveChanged; 

        // SystemResourcesAreChanging is used by FE when coercing the font properties to determine 
        // if it should return the current system metric or the value passed to the coerce callback
        [ThreadStatic]
        internal static bool SystemResourcesAreChanging;
        #endregion 
    }
 
    internal class DeferredResourceReference : DeferredReference 
    {
        #region Constructor 

        internal DeferredResourceReference(ResourceDictionary dictionary, object key)
        {
            _dictionary = dictionary; 
            _keyOrValue = key;
        } 
 
        #endregion Constructor
 
        #region Methods

        internal override object GetValue(BaseValueSourceInternal valueSource)
        { 
            // If the _value cache is invalid fetch the value from
            // the dictionary else just retun the cached value 
            if (_dictionary != null) 
            {
                bool canCache; 
                object value  = _dictionary.GetValue(_keyOrValue, out canCache);
                if (!CheckIfShared || canCache)
                {
                    // Note that we are replacing the _keyorValue field 
                    // with the value and nuking the _dictionary field.
                    _keyOrValue = value; 
                    RemoveFromDictionary(); 
                }
 
                // Freeze if this value originated from a style or template
                bool freezeIfPossible =
                    valueSource == BaseValueSourceInternal.ThemeStyle ||
                    valueSource == BaseValueSourceInternal.ThemeStyleTrigger || 
                    valueSource == BaseValueSourceInternal.Style ||
                    valueSource == BaseValueSourceInternal.TemplateTrigger || 
                    valueSource == BaseValueSourceInternal.StyleTrigger || 
                    valueSource == BaseValueSourceInternal.ParentTemplate ||
                    valueSource == BaseValueSourceInternal.ParentTemplateTrigger; 

                // This is to freeze values produced by deferred
                // references within styles and templates
                if (freezeIfPossible) 
                {
                    StyleHelper.SealIfSealable(value); 
                } 

                // tell any listeners (e.g. ResourceReferenceExpressions) 
                // that the value has been inflated
                if (Inflated != null)
                {
                    Inflated(this, EventArgs.Empty); 
                }
 
                return value; 
            }
 
            return _keyOrValue;
        }

        // Gets the type of the value it represents 
        internal override Type GetValueType()
        { 
            if (_dictionary != null) 
            {
                // Take a peek at the element type of the ElementStartRecord 
                // within the ResourceDictionary's deferred content.
                bool found;
                return _dictionary.GetValueType(_keyOrValue, out found);
            } 
            else
            { 
                return _keyOrValue != null ? _keyOrValue.GetType() : null; 
            }
        } 

        // remove this DeferredResourceReference from its ResourceDictionary
        internal virtual void RemoveFromDictionary()
        { 
            if (_dictionary != null)
            { 
                _dictionary.DeferredResourceReferences.Remove(this); 
                _dictionary = null;
            } 
        }

        #endregion Methods
 
        #region Properties
 
        internal virtual object Key 
        {
            get { return _keyOrValue; } 
        }

        internal ResourceDictionary Dictionary
        { 
            get { return _dictionary; }
            set { _dictionary = value; } 
        } 

        internal virtual object Value 
        {
            get { return _keyOrValue; }
            set { _keyOrValue = value; }
        } 

        internal virtual bool IsUnset 
        { 
            get { return false; }
        } 

        internal bool IsInflated
        {
            get { return (_dictionary == null); } 
        }
 
        internal bool CheckIfShared 
        {
            get { return _checkIfShared; } 
            set { _checkIfShared = value; }
        }

        #endregion Properties 

        #region Events 
 
        internal event EventHandler Inflated;
 
        #endregion Events

        #region Data
 
        private ResourceDictionary _dictionary;
        protected object _keyOrValue; 
        private bool _checkIfShared; 

        #endregion Data 
    }

    internal class DeferredAppResourceReference : DeferredResourceReference
    { 
        #region Constructor
 
        internal DeferredAppResourceReference(ResourceDictionary dictionary, object resourceKey) 
            : base(dictionary, resourceKey)
        { 
        }

        #endregion Constructor
 
        #region Methods
 
        internal override object GetValue(BaseValueSourceInternal valueSource) 
        {
            lock (((ICollection)Application.Current.Resources).SyncRoot) 
            {
                return base.GetValue(valueSource);
            }
        } 

        // Gets the type of the value it represents 
        internal override Type GetValueType() 
        {
            lock (((ICollection)Application.Current.Resources).SyncRoot) 
            {
                return base.GetValueType();
            }
        } 

        #endregion Methods 
    } 

    internal class DeferredThemeResourceReference : DeferredResourceReference 
    {
        #region Constructor

        internal DeferredThemeResourceReference(ResourceDictionary dictionary, object resourceKey) 
            :base(dictionary, resourceKey)
        { 
        } 

        #endregion Constructor 

        #region Methods

        internal override object GetValue(BaseValueSourceInternal valueSource) 
        {
            lock (SystemResources.ThemeDictionaryLock) 
            { 
                // If the value cache is invalid fetch the value from
                // the dictionary else just retun the cached value 
                if (Dictionary != null)
                {
                    bool canCache;
                    object key = Key; 
                    object value;
 
                    SystemResources.IsSystemResourcesParsing = true; 

                    try 
                    {
                        value = Dictionary.GetValue(key, out canCache);
                        if (!CheckIfShared || canCache)
                        { 
                            // Note that we are replacing the _keyorValue field
                            // with the value and nuking the _dictionary field. 
                            Value = value; 
                            Dictionary = null;
                        } 
                    }
                    finally
                    {
                        SystemResources.IsSystemResourcesParsing = false; 
                    }
 
                    // Only cache keys that would be located by FindResourceInternal 
                    if ((key is Type || key is ResourceKey) && canCache)
                    { 
                        SystemResources.CacheResource(key, value, false /*isTraceEnabled*/);
                    }

                    return value; 
                }
 
                return Value; 
            }
        } 

        // Gets the type of the value it represents
        internal override Type GetValueType()
        { 
            lock (SystemResources.ThemeDictionaryLock)
            { 
                return base.GetValueType(); 
            }
        } 

        // remove this DeferredResourceReference from its ResourceDictionary
        internal override void RemoveFromDictionary()
        { 
            // DeferredThemeResourceReferences are never added to the dictionary's
            // list of deferred references, so they don't need to be removed. 
        } 

        #endregion Methods 
    }

    /// 
    /// This signifies a DeferredResourceReference that is used as a place holder 
    /// for the front loaded StaticResource within a deferred content section.
    ///  
    internal class DeferredResourceReferenceHolder : DeferredResourceReference 
    {
        #region Constructor 

        internal DeferredResourceReferenceHolder(object resourceKey, object value)
            :base(null, null)
        { 
            _keyOrValue = new object[]{resourceKey, value};
        } 
 
        #endregion Constructor
 
        #region Methods

        internal override object GetValue(BaseValueSourceInternal valueSource)
        { 
            return Value;
        } 
 
        // Gets the type of the value it represents
        internal override Type GetValueType() 
        {
            object value = Value;
            return value != null ? value.GetType() : null;
        } 

        #endregion Methods 
 
        #region Properties
 
        internal override object Key
        {
            get { return ((object[])_keyOrValue)[0]; }
        } 

        internal override object Value 
        { 
            get { return ((object[])_keyOrValue)[1]; }
            set { ((object[])_keyOrValue)[1] = value; } 
        }

        internal override bool IsUnset
        { 
            get { return Value == DependencyProperty.UnsetValue; }
        } 
 
        #endregion Properties
    } 

}

 

 

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

using System; 
using System.Diagnostics; 
using System.IO;
using System.Reflection; 
using System.Resources;
using System.Runtime.InteropServices;
using System.Collections;
using System.Collections.Generic; 
using System.Globalization;
using System.Security; 
using System.Security.Permissions; 
using System.Windows.Threading;
using System.Text; 
using MS.Utility;
using System.Windows.Controls.Primitives;
using System.Windows.Markup;
using System.Windows.Documents; 
using System.Windows.Media;
using System.Windows.Input; 
using System.Windows.Resources; 
using MS.Win32;
using MS.Internal; 
using MS.Internal.Ink;
using MS.Internal.PresentationFramework;                   // SafeSecurityHelper

// Disable pragma warnings to enable PREsharp pragmas 
#pragma warning disable 1634, 1691
 
namespace System.Windows 
{
    ///  
    ///     SystemResources loads system theme data into the system resources collection.
    /// 
    internal static class SystemResources
    { 
        // ------------------------------------------------
        // 
        // Methods 
        //
        // ------------------------------------------------ 

        #region Methods

        ///  
        ///     Returns a resource for the given key type from the system resources collection.
        ///  
        /// The resource id to search for. 
        /// The resource if it exists, null otherwise.
        //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647 
        internal static object FindThemeStyle(DependencyObjectType key)
        {
            // Find a cached theme style
            object resource = _themeStyleCache[key]; 
            if (resource != null)
            { 
                // Found a cached value 
                if (resource == _specialNull)
                { 
                    // We cached a null, set it to a real null
                    return null; // Null resource found
                }
 
                return resource;
            } 
 
            // Find the resource from the system resources collection
            resource = FindResourceInternal(key.SystemType); 

            // The above read operation was lock free. Writing
            // to the cache will need a lock though
            lock (ThemeDictionaryLock) 
            {
                if (resource != null) 
                { 
                    // Cache the value
                    _themeStyleCache[key] = resource; 
                }
                else
                {
                    // Record nulls so we don't bother doing lookups for them later 
                    // Any theme changes will clear these values
                    _themeStyleCache[key] = _specialNull; 
                } 
            }
 
            return resource;
        }

        ///  
        ///     Returns a resource of the given name from the system resources collection.
        ///  
        /// The resource id to search for. 
        /// The resource if it exists, null otherwise.
        //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647 
        internal static object FindResourceInternal(object key)
        {
            // Call Forwarded
            return FindResourceInternal(key, false /*allowDeferredResourceReference*/, false /*mustReturnDeferredResourceReference*/); 
        }
 
        internal static object FindResourceInternal(object key, bool allowDeferredResourceReference, bool mustReturnDeferredResourceReference) 
        {
            // Ensure that resource changes on this thread can be heard and handled 
            EnsureResourceChangeListener();

            object resource = null;
            Type typeKey = null; 
            ResourceKey resourceKey = null;
 
            bool isTraceEnabled = EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.verbose); 

            // System resource keys can only be of type Type or of type ResourceKey 
            typeKey = key as Type;
            resourceKey = (typeKey == null) ? (key as ResourceKey) : null;

            if (isTraceEnabled) 
            {
                EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.RESOURCEFINDGUID), 
                                                    MS.Utility.EventType.StartEvent, 
                                                    (key == null) ? "null" : key.ToString());
            } 


            if ((typeKey == null) && (resourceKey == null))
            { 
                // Not a valid key
                if (isTraceEnabled) 
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.RESOURCEFINDGUID), MS.Utility.EventType.EndEvent);
                } 
                return null;
            }

            // Check if the value was already cached 
            if (!FindCachedResource(key, ref resource, mustReturnDeferredResourceReference))
            { 
                // Cache miss, do a lookup 
                if (isTraceEnabled)
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.RESOURCECACHEMISSGUID), MS.Utility.EventType.Info);
                }

                lock (ThemeDictionaryLock) 
                {
                    bool canCache = true; 
                    SystemResourceKey sysKey = (resourceKey != null) ? resourceKey as SystemResourceKey : null; 
                    if (sysKey != null)
                    { 
                        // Check the list of system metrics
                        if (!mustReturnDeferredResourceReference)
                        {
                            resource = sysKey.Resource; 
                        }
                        else 
                        { 
                            resource = new DeferredResourceReferenceHolder(sysKey, sysKey.Resource);
                        } 
                        if (isTraceEnabled)
                        {
                            EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.RESOURCESTOCKGUID),
                                                                 MS.Utility.EventType.Info, 
                                                                 sysKey.ToString());
                        } 
                    } 
                    else
                    { 
                        // Do a dictionary lookup
                        resource = FindDictionaryResource(key, typeKey, resourceKey, isTraceEnabled, allowDeferredResourceReference, mustReturnDeferredResourceReference, out canCache);
                    }
 
                    if ((canCache && !allowDeferredResourceReference) || resource == null)
                    { 
                        // Cache the resource 
                        CacheResource(key, resource, isTraceEnabled);
                    } 
                }
            }

            if (isTraceEnabled) 
            {
                EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.RESOURCEFINDGUID), MS.Utility.EventType.EndEvent); 
            } 

            return resource; 
        }

        #endregion
 
        // ------------------------------------------------
        // 
        // Implementation 
        //
        // ------------------------------------------------ 

        #region Implementation

        //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647 
        internal static void CacheResource(object key, object resource, bool isTraceEnabled)
        { 
            // Thread safety handled by FindResourceInternal. Be sure to have locked _resourceCache.SyncRoot. 

            if (resource != null) 
            {
                // Cache the value
                _resourceCache[key] = resource;
 
                if (isTraceEnabled)
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.RESOURCECACHEVALUEGUID), MS.Utility.EventType.Info); 
                }
            } 
            else
            {
                // Record nulls so we don't bother doing lookups for them later
                // Any theme changes will clear these values 
                _resourceCache[key] = _specialNull;
 
                if (isTraceEnabled) 
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.RESOURCECACHENULLGUID), MS.Utility.EventType.Info); 
                }
            }
        }
 
        #region Resource Value Lookup
 
        private static bool FindCachedResource(object key, ref object resource, bool mustReturnDeferredResourceReference) 
        {
            // reading the cache is lock free 

            resource = _resourceCache[key];
            bool found = (resource != null);
 
            if (resource == _specialNull)
            { 
                // We cached a null, set it to a real null 
                resource = null;
            } 
            else
            {
                DispatcherObject dispatcherObject = resource as DispatcherObject;
                if (dispatcherObject != null) 
                {
                    // The current thread may not have access to this object. 
                    dispatcherObject.VerifyAccess(); 
                }
            } 

            if (found && mustReturnDeferredResourceReference)
            {
                resource = new DeferredResourceReferenceHolder(key, resource); 
            }
 
            return found; 
        }
 
        /// 
        ///     Searches for a resource inside a ResourceDictionary.
        /// 
        /// The original key. 
        /// The key cast to Type.
        /// The key cast to ResourceKey. 
        /// Tracing on/off. 
        /// 
        ///     If this flag is true the resource will not actually be inflated from Baml. 
        ///     Instead we will return an instance of DeferredDictionaryReference which
        ///     can later be used to query the resource
        /// 
        ///  
        ///     If this method is true this method will always return a
        ///     DeferredThemeResourceReference instance which envelopes the underlying resource. 
        ///  
        /// Whether callers can cache the value.
        ///  
        private static object FindDictionaryResource(
            object      key,
            Type        typeKey,
            ResourceKey resourceKey, 
            bool        isTraceEnabled,
            bool        allowDeferredResourceReference, 
            bool        mustReturnDeferredResourceReference, 
            out bool    canCache)
        { 
            // Thread safety handled by FindResourceInternal. Be sure to have locked _resourceCache.SyncRoot.

            Debug.Assert(typeKey != null || resourceKey != null, "typeKey or resourceKey should be non-null");
 
            canCache = true;
            object resource = null; 
            Assembly assembly = (typeKey != null) ? typeKey.Assembly : resourceKey.Assembly; 

            if ((assembly == null) || IgnoreAssembly(assembly)) 
            {
                // Without an assembly, we can't figure out which dictionary to look at.
                // Also, ignore some common assemblies we know to not contain resources.
                return null; 
            }
 
            ResourceDictionaries dictionaries = EnsureDictionarySlot(assembly); 
            ResourceDictionary dictionary = dictionaries.LoadThemedDictionary(isTraceEnabled);
            if (dictionary != null) 
            {
                resource = LookupResourceInDictionary(dictionary, key, allowDeferredResourceReference, mustReturnDeferredResourceReference, out canCache);
            }
 
            if (resource == null)
            { 
                dictionary = dictionaries.LoadGenericDictionary(isTraceEnabled); 
                if (dictionary != null)
                { 
                    resource = LookupResourceInDictionary(dictionary, key, allowDeferredResourceReference, mustReturnDeferredResourceReference, out canCache);
                }
            }
 
            if (resource != null)
            { 
                // Resources coming out of the dictionary may need to be frozen 
                Freeze(resource);
            } 

            return resource;
        }
 
        /// 
        ///     Looks in the ResourceDictionary for the desired resource. 
        ///  
        /// The ResourceDictionary to look in.
        /// The key for the resource. 
        /// 
        ///     If this flag is true the resource will not actually be inflated from Baml.
        ///     Instead we will return an instance of DeferredDictionaryReference which
        ///     can later be used to query the resource 
        /// 
        ///  
        ///     If this method is true this method will always return a 
        ///     DeferredThemeResourceReference instance which envelopes the underlying resource.
        ///  
        /// Whether callers should cache the value.
        /// The resource if found and successfully loaded, null otherwise.
        private static object LookupResourceInDictionary(
            ResourceDictionary  dictionary, 
            object              key,
            bool                allowDeferredResourceReference, 
            bool                mustReturnDeferredResourceReference, 
            out bool            canCache)
        { 
            object resource = null;
            IsSystemResourcesParsing = true;

            try 
            {
                resource = dictionary.FetchResource(key, allowDeferredResourceReference, mustReturnDeferredResourceReference, out canCache); 
            } 
            finally
            { 
                IsSystemResourcesParsing = false;
            }

            return resource; 
        }
 
        ///  
        ///     Unbinds a Freezable from its Context.
        ///  
        /// The resource to freeze.
        private static void Freeze(object resource)
        {
            Freezable freezable = resource as Freezable; 
            if (freezable != null && !freezable.IsFrozen)
            { 
                freezable.Freeze(); 
            }
        } 

        #endregion

        #region Dictionary Loading 

        ///  
        ///     Returns the dictionary cache slot associated with the given assembly. 
        /// 
        /// The desired assembly 
        /// The cache slot.
        private static ResourceDictionaries EnsureDictionarySlot(Assembly assembly)
        {
            ResourceDictionaries dictionaries = null; 
            if (_dictionaries != null)
            { 
                _dictionaries.TryGetValue(assembly, out dictionaries); 
            }
            else 
            {
                // We will be caching data, create the cache
                _dictionaries = new Dictionary(1);
            } 

            if (dictionaries == null) 
            { 
                // Ensure the cache slot is created
                dictionaries = new ResourceDictionaries(assembly); 
                _dictionaries.Add(assembly, dictionaries);
            }

            return dictionaries; 
        }
 
        private static bool IgnoreAssembly(Assembly assembly) 
        {
            return (assembly == MsCorLib) || (assembly == PresentationCore) || (assembly == WindowsBase); 
        }

        private static Assembly MsCorLib
        { 
            get
            { 
                if (_mscorlib == null) 
                {
                    _mscorlib = typeof(string).Assembly; 
                }

                return _mscorlib;
            } 
        }
 
        private static Assembly PresentationFramework 
        {
            get 
            {
                if (_presentationFramework == null)
                {
                    _presentationFramework = typeof(FrameworkElement).Assembly; 
                }
 
                return _presentationFramework; 
            }
        } 

        private static Assembly PresentationCore
        {
            get 
            {
                if (_presentationCore == null) 
                { 
                    _presentationCore = typeof(UIElement).Assembly;
                } 

                return _presentationCore;
            }
        } 

        private static Assembly WindowsBase 
        { 
            get
            { 
                if (_windowsBase == null)
                {
                    _windowsBase = typeof(DependencyObject).Assembly;
                } 

                return _windowsBase; 
            } 
        }
 
        /// 
        ///     Loads and caches the generic and themed resource dictionaries for an assembly.
        /// 
        internal class ResourceDictionaries 
        {
            ///  
            ///     Creates an instance of this class. 
            /// 
            /// The assembly that this class represents. 
            internal ResourceDictionaries(Assembly assembly)
            {
                _assembly = assembly;
                if (assembly == PresentationFramework) 
                {
                    // Since we know all the information about PresentationFramework in advance, 
                    // we can pre-initialize that data. 
                    _assemblyName = PresentationFrameworkName;
 
                    // There is no generic dictionary
                    _genericDictionary = null;
                    _genericLoaded = true;
                    _genericLocation = ResourceDictionaryLocation.None; 

                    // Themed dictionaries are all external 
                    _themedLocation = ResourceDictionaryLocation.ExternalAssembly; 
                    _locationsLoaded = true;
                } 
                else
                {
                    _assemblyName = SafeSecurityHelper.GetAssemblyPartialName(assembly);
                } 
            }
 
            ///  
            ///     Resets the themed dictionaries. This is used when the theme changes.
            ///  
            internal void ClearThemedDictionary()
            {
                _themedLoaded = false;
                _themedDictionary = null; 
            }
 
            ///  
            ///     Returns the theme dictionary associated with this assembly.
            ///  
            /// Whether debug tracing is enabled.
            /// The dictionary if loaded, otherwise null.
            internal ResourceDictionary LoadThemedDictionary(bool isTraceEnabled)
            { 
                if (!_themedLoaded)
                { 
                    LoadDictionaryLocations(); 

                    if (_preventReEnter || (_themedLocation == ResourceDictionaryLocation.None)) 
                    {
                        // We are already in the middle of parsing this resource dictionary, avoid infinite loops.
                        // OR, there are no themed resources.
                        return null; 
                    }
 
                    IsSystemResourcesParsing = true; 
                    _preventReEnter = true;
                    try 
                    {
                        ResourceDictionary dictionary = null;

                        // Get the assembly to look inside for resources. 
                        Assembly assembly;
                        string assemblyName; 
                        bool external = (_themedLocation == ResourceDictionaryLocation.ExternalAssembly); 
                        if (external)
                        { 
                            LoadExternalAssembly(false /* classic */, false /* generic */, out assembly, out assemblyName);
                        }
                        else
                        { 
                            assembly = _assembly;
                            assemblyName = _assemblyName; 
                        } 

                        if (assembly != null) 
                        {
                            dictionary = LoadDictionary(assembly, assemblyName, ThemedResourceName, isTraceEnabled);
                            if ((dictionary == null) && !external)
                            { 
                                // Themed resources should have been inside the source assembly, but failed to load.
                                // Try falling back to external in case this is a theme that shipped later. 
                                LoadExternalAssembly(false /* classic */, false /* generic */, out assembly, out assemblyName); 
                                if (assembly != null)
                                { 
                                    dictionary = LoadDictionary(assembly, assemblyName, ThemedResourceName, isTraceEnabled);
                                }
                            }
                        } 

                        if ((dictionary == null) && UxThemeWrapper.IsActive) 
                        { 
                            // If a non-classic dictionary failed to load, then try to load classic.
                            if (external) 
                            {
                                LoadExternalAssembly(true /* classic */, false /* generic */, out assembly, out assemblyName);
                            }
                            else 
                            {
                                assembly = _assembly; 
                                assemblyName = _assemblyName; 
                            }
 
                            if (assembly != null)
                            {
                                dictionary = LoadDictionary(assembly, assemblyName, ClassicResourceName, isTraceEnabled);
                            } 
                        }
 
                        _themedDictionary = dictionary; 
                        _themedLoaded = true;
                    } 
                    finally
                    {
                        _preventReEnter = false;
                        IsSystemResourcesParsing = false; 
                    }
                } 
 
                return _themedDictionary;
            } 

            /// 
            ///     Returns the generic dictionary associated with this assembly.
            ///  
            /// Whether debug tracing is enabled.
            /// The dictionary if loaded, otherwise null. 
            internal ResourceDictionary LoadGenericDictionary(bool isTraceEnabled) 
            {
                if (!_genericLoaded) 
                {
                    LoadDictionaryLocations();

                    if (_preventReEnter || (_genericLocation == ResourceDictionaryLocation.None)) 
                    {
                        // We are already in the middle of parsing this resource dictionary, avoid infinite loops. 
                        return null; 
                    }
 
                    IsSystemResourcesParsing = true;
                    _preventReEnter = true;
                    try
                    { 
                        ResourceDictionary dictionary = null;
 
                        // Get the assembly to look inside 
                        Assembly assembly;
                        string assemblyName; 
                        if (_genericLocation == ResourceDictionaryLocation.ExternalAssembly)
                        {
                            LoadExternalAssembly(false /* classic */, true /* generic */, out assembly, out assemblyName);
                        } 
                        else
                        { 
                            assembly = _assembly; 
                            assemblyName = _assemblyName;
                        } 

                        if (assembly != null)
                        {
                            dictionary = LoadDictionary(assembly, assemblyName, GenericResourceName, isTraceEnabled); 
                        }
 
                        _genericDictionary = dictionary; 
                        _genericLoaded = true;
                    } 
                    finally
                    {
                        _preventReEnter = false;
                        IsSystemResourcesParsing = false; 
                    }
                } 
 
                return _genericDictionary;
            } 

            /// 
            ///     Loads the assembly attribute indicating where dictionaries are stored.
            ///  
            private void LoadDictionaryLocations()
            { 
                if (!_locationsLoaded) 
                {
                    ThemeInfoAttribute locations = ThemeInfoAttribute.FromAssembly(_assembly); 
                    if (locations != null)
                    {
                        _themedLocation = locations.ThemeDictionaryLocation;
                        _genericLocation = locations.GenericDictionaryLocation; 
                    }
                    else 
                    { 
                        _themedLocation = ResourceDictionaryLocation.None;
                        _genericLocation = ResourceDictionaryLocation.None; 
                    }
                    _locationsLoaded = true;
                }
            } 

            ///  
            ///     Loads an associated theme assembly based on a main assembly. 
            /// 
            private void LoadExternalAssembly(bool classic, bool generic, out Assembly assembly, out string assemblyName) 
            {
                StringBuilder sb = new StringBuilder(_assemblyName.Length + 10);

                sb.Append(_assemblyName); 
                sb.Append(".");
 
                if (generic) 
                {
                    sb.Append("generic"); 
                }
                else if (classic)
                {
                    sb.Append("classic"); 
                }
                else 
                { 
                    sb.Append(UxThemeWrapper.ThemeName);
                } 

                assemblyName = sb.ToString();
                string fullName = SafeSecurityHelper.GetFullAssemblyNameFromPartialName(_assembly, assemblyName);
 
                assembly = null;
                try 
                { 
                    assembly = Assembly.Load(fullName);
                } 
                // There is no Assembly.Exists API to determine if an Assembly exists.
                // There is also no way to determine if an Assembly's format is good prior to loading it.
                // So, the exception must be caught. assembly will continue to be null and returned.
#pragma warning disable 6502 
                catch (FileNotFoundException)
                { 
                } 
                catch (BadImageFormatException)
                { 
                }
#pragma warning restore 6502
            }
 
            /// 
            ///     The string to use as the key to load the .NET resource stream that contains themed resources. 
            ///  
            internal static string ThemedResourceName
            { 
                get
                {
                    if (_themedResourceName == null)
                    { 
                        if (UxThemeWrapper.IsActive)
                        { 
                            _themedResourceName = "themes/" + UxThemeWrapper.ThemeName.ToLowerInvariant() + "." + UxThemeWrapper.ThemeColor.ToLowerInvariant(); 
                        }
                        else 
                        {
                            _themedResourceName = ClassicResourceName;
                        }
                    } 

                    return _themedResourceName; 
                } 
            }
 
            /// 
            ///     Loads a ResourceDictionary from within an assembly's .NET resource store.
            /// 
            /// The owning assembly. 
            /// The name of the owning assembly.
            /// The name of the desired theme resource. 
            /// Whether tracing is enabled. 
            /// The dictionary if found and loaded successfully, null otherwise.
            private ResourceDictionary LoadDictionary(Assembly assembly, string assemblyName, string resourceName, bool isTraceEnabled) 
            {
                ResourceDictionary dictionary = null;

                // Create the resource manager that will load the byte array 
                ResourceManager rm = new ResourceManager(assemblyName + ".g", assembly);
 
                resourceName = resourceName + ".baml"; 
                // Load the resource stream
                Stream stream = null; 
                try
                {
                    stream = rm.GetStream(resourceName, CultureInfo.CurrentUICulture);
                } 
                // There is no ResourceManager.HasManifest in order to detect this case before an exception is thrown.
                // Likewise, there is no way to know if loading a resource will fail prior to loading it. 
                // So, the exceptions must be caught. stream will continue to be null and handled accordingly later. 
#pragma warning disable 6502
 
                catch (MissingManifestResourceException)
                {
                    // No usable resources in the assembly
                } 
#if !DEBUG
                catch (InvalidOperationException) 
                { 
                    // Object not stored correctly
                } 
#endif

#pragma warning restore 6502
 
                if (stream != null)
                { 
                    ParserContext pc = new ParserContext(); 

                    // The stream is actually owned by the theme engine and will remain open 
                    // as long as the loading process is alive. So this can be re-used by the
                    // parser when loading defered content like this dictionary instead of creating
                    // a new memory buffer.
                    pc.OwnsBamlStream = true; 

                    dictionary = (ResourceDictionary)XamlReader.LoadBaml( 
                        stream,                             // Stream input 
                        pc,                                 // Parser Context
                        null,                               // Owner element 
                        false);                             // Do not Close the stream

                    if (isTraceEnabled && (dictionary != null))
                    { 
                        EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.RESOURCEBAMLASSEMBLYGUID),
                                                             MS.Utility.EventType.Info, 
                                                             assemblyName); 
                    }
                } 

                return dictionary;
            }
 
            internal static void OnThemeChanged()
            { 
                _themedResourceName = null; 
            }
 
            private ResourceDictionary _genericDictionary;
            private ResourceDictionary _themedDictionary;
            private bool _genericLoaded = false;
            private bool _themedLoaded = false; 
            private bool _preventReEnter = false;
            private bool _locationsLoaded = false; 
            private string _assemblyName; 
            private Assembly _assembly;
            private ResourceDictionaryLocation _genericLocation; 
            private ResourceDictionaryLocation _themedLocation;

            private static string _themedResourceName;
        } 

        #endregion 
 
        #region Value Changes
 
        // The hwndNotify is referenced by the _hwndNotify static field, but
        // PreSharp will think that the hwndNotify is local and should be disposed.
#pragma warning disable 6518
 
        ///
        ///     Critical - Creates an HwndWrapper and adds a hook. 
        ///     TreatAsSafe: The _hwndNotify window is critical and this function is safe to call 
        ///
        [SecurityCritical,SecurityTreatAsSafe] 
        private static void EnsureResourceChangeListener()
        {
            // Create a new notify window if we haven't already created one for this thread.
            if (_hwndNotify == null) 
            {
                // Create a top-level, invisible window so we can get the WM_THEMECHANGE notification. 
                HwndWrapper hwndNotify; 
                hwndNotify = new HwndWrapper(0, NativeMethods.WS_POPUP, 0, 0, 0, 0, 0, "SystemResourceNotifyWindow", IntPtr.Zero, null);
                _hwndNotify = new SecurityCriticalDataClass(hwndNotify); 
                _hwndNotify.Value.Dispatcher.ShutdownFinished += OnShutdownFinished;
                _hwndNotifyHook = new HwndWrapperHook(SystemThemeFilterMessage);
                _hwndNotify.Value.AddHook(_hwndNotifyHook);
            } 
        }
 
        /// 
        ///     Critical - Calls dispose on the critical hwnd wrapper.
        ///     TreatAsSafe: It is safe to dispose the wrapper 
        ///
        [SecurityCritical, SecurityTreatAsSafe]
        private static void OnShutdownFinished(object sender, EventArgs args)
        { 
            if (_hwndNotify != null)
                _hwndNotify.Value.Dispose(); 
 
            _hwndNotifyHook = null;
            _hwndNotify = null; 
        }

#pragma warning restore 6518
 
        private static void OnThemeChanged()
        { 
            ResourceDictionaries.OnThemeChanged(); 
            UxThemeWrapper.OnThemeChanged();
            ThemeDictionaryExtension.OnThemeChanged(); 

            lock (ThemeDictionaryLock)
            {
                // Clear the resource cache 
                _resourceCache.Clear();
 
                // Clear the themeStyleCache 
                _themeStyleCache.Clear();
 
                // Clear the themed dictionaries
                if (_dictionaries != null)
                {
                    foreach (ResourceDictionaries dictionaries in _dictionaries.Values) 
                    {
                        dictionaries.ClearThemedDictionary(); 
                    } 
                }
            } 
        }

        private static void OnSystemValueChanged()
        { 
            lock (ThemeDictionaryLock)
            { 
                // Collect the list of keys for the values that will need to be removed 
                // Note: We don't immediately remove them because the Key list is not
                // static. 

                List keys = new List();

                foreach (object key in _resourceCache.Keys) 
                {
                    SystemResourceKey resKey = key as SystemResourceKey; 
                    if (resKey != null) 
                    {
                        keys.Add(resKey); 
                    }
                }

                // Remove the values 

                int count = keys.Count; 
                for (int i = 0; i < count; i++) 
                {
                    _resourceCache.Remove(keys[i]); 
                }
            }
        }
 
        private static object InvalidateTreeResources(Object args)
        { 
            object[] argsArray = (object[])args; 
            PresentationSource source = (PresentationSource)argsArray[0];
            if (!source.IsDisposed) 
            {
                FrameworkElement fe = source.RootVisual as FrameworkElement;
                if (fe != null)
                { 
                    bool isSysColorsOrSettingsChange = (bool)argsArray[1];
                    if (isSysColorsOrSettingsChange) 
                    { 
                        TreeWalkHelper.InvalidateOnResourcesChange(fe, null, ResourcesChangeInfo.SysColorsOrSettingsChangeInfo);
                    } 
                    else
                    {
                        TreeWalkHelper.InvalidateOnResourcesChange(fe, null, ResourcesChangeInfo.ThemeChangeInfo);
                    } 

                    System.Windows.Input.KeyboardNavigation.AlwaysShowFocusVisual = SystemParameters.KeyboardCues; 
                    fe.CoerceValue(System.Windows.Input.KeyboardNavigation.ShowKeyboardCuesProperty); 

                    SystemResourcesAreChanging = true; 
                    // Update FontFamily properties on root elements
                    fe.CoerceValue(TextElement.FontFamilyProperty);
                    fe.CoerceValue(TextElement.FontSizeProperty);
                    fe.CoerceValue(TextElement.FontStyleProperty); 
                    fe.CoerceValue(TextElement.FontWeightProperty);
                    SystemResourcesAreChanging = false; 
 
                    PopupRoot popupRoot = fe as PopupRoot;
                    if (popupRoot != null && popupRoot.Parent != null) 
                    {
                        popupRoot.Parent.CoerceValue(Popup.HasDropShadowProperty);
                    }
                } 
            }
 
            return null; 
        }
 
        /// 
        /// This method calls into PresentationCore internally to update Tabelt devices when the system settings change.
        /// 
        ///  
        /// 
        ///  
        ///  
        ///     Critical - Accesses the critical data.
        ///                 _hwndNotify 
        /// 
        [SecurityCritical]
        private static void InvalidateTabletDevices(int msg, IntPtr wParam, IntPtr lParam)
        { 
            if ( _hwndNotify != null )
            { 
                Dispatcher dispatcher = _hwndNotify.Value.Dispatcher; 
                if ( dispatcher != null && dispatcher.InputManager != null )
                { 
                    ((InputManager)dispatcher.InputManager).StylusLogic.HandleMessage(msg, wParam, lParam);
                }
            }
        } 

        /// 
        ///     Critical - calls CriticalCurrentSources. 
        ///     TreatAsSafe - invalidation of resources considered ok.
        ///                   Net effect is an invalidation of tree and reload of BAML from theme files. 
        ///                   Worse that could happen is a DOS attack within the app.
        ///
        [SecurityCritical, SecurityTreatAsSafe ]
        private static void InvalidateResources(bool isSysColorsOrSettingsChange) 
        {
            SystemResourcesHaveChanged = true; 
 
            Dispatcher dispatcher = isSysColorsOrSettingsChange ? null : Dispatcher.FromThread(System.Threading.Thread.CurrentThread);
            if (dispatcher != null || isSysColorsOrSettingsChange) 
            {
                foreach (PresentationSource source in PresentationSource.CriticalCurrentSources)
                {
                    if (!source.IsDisposed && (isSysColorsOrSettingsChange || (source.Dispatcher == dispatcher))) 
                    {
                        source.Dispatcher.BeginInvoke(DispatcherPriority.Normal, 
                                                      new DispatcherOperationCallback(InvalidateTreeResources), 
                                                      new object[]{source, isSysColorsOrSettingsChange});
                    } 
                }
            }
        }
        ///  
        ///     Critical: This code calls into PeekMessage and can be used to spoof theme change messages
        ///     TreatAsSafe:The call to PeekMessage is safe and no information is exposed. In the case of the 
        ///     messages handled in this function, no data is passed in or out, the only form of attack possible 
        ///     here is DOS by excessive calls to this.
        ///  
        [SecurityCritical,SecurityTreatAsSafe]
        private static IntPtr SystemThemeFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            switch (msg) 
            {
                case NativeMethods.WM_DEVICECHANGE: 
                    InvalidateTabletDevices(msg, wParam, lParam); 

                    // If there was an invalidation made to a Mouse metric, 
                    // then resource references need to be invalidated.
                    if (SystemParameters.InvalidateDeviceDependentCache())
                    {
                        OnSystemValueChanged(); 
                        InvalidateResources(true); // Invalidate all resource since this should happen only once
                    } 
                    break; 

                case NativeMethods.WM_DISPLAYCHANGE: 
                    InvalidateTabletDevices(msg, wParam, lParam);

                    // If there was an invalidation made to a Display metric,
                    // then resource references need to be invalidated. 
                    if (SystemParameters.InvalidateDisplayDependentCache())
                    { 
                        OnSystemValueChanged(); 
                        InvalidateResources(true); // Invalidate all resource since this should happen only once
                    } 
                    break;

                case NativeMethods.WM_POWERBROADCAST:
                    // If there was an invalidation made to a Power Setting, 
                    // then resource references need to be invalidated.
                    if (NativeMethods.IntPtrToInt32(wParam) == NativeMethods.PBT_APMPOWERSTATUSCHANGE && 
                        SystemParameters.InvalidatePowerDependentCache()) 
                    {
                        OnSystemValueChanged(); 
                        InvalidateResources(true); // Invalidate all resource since this should happen only once
                    }
                    break;
 
                case NativeMethods.WM_THEMECHANGED:
                    bool usingSendMessage = SafeNativeMethods.InSendMessage(); 
                    if (!usingSendMessage) 
                    {
                        System.Windows.Interop.MSG m = new System.Windows.Interop.MSG(); 
                        bool moreMessagesPosted = UnsafeNativeMethods.PeekMessage(ref m, new HandleRef(null, hwnd), NativeMethods.WM_THEMECHANGED, NativeMethods.WM_THEMECHANGED, NativeMethods.PM_NOREMOVE);
                        if (!moreMessagesPosted)
                        {
                            SystemColors.InvalidateCache(); 
                            SystemParameters.InvalidateCache();
                            OnThemeChanged(); 
                            InvalidateResources(false); // Only invalidate this thread's resources, other threads will get a chance 
                        }
                    } 
                    break;

                case NativeMethods.WM_SYSCOLORCHANGE:
                    // If there was an invalidation made to a system color or brush, 
                    // then resource references need to be invalidated.
                    if (SystemColors.InvalidateCache()) 
                    { 
                        OnSystemValueChanged();
                        InvalidateResources(true); // Invalidate all resource since this should happen only once 
                    }
                    break;

                case NativeMethods.WM_SETTINGCHANGE: 
                    InvalidateTabletDevices(msg, wParam, lParam); // Update tablet device settings
 
                    // If there was an invalidation made to a system param or metric, 
                    // then resource references need to be invalidated.
                    if (SystemParameters.InvalidateCache((int)wParam)) 
                    {
                        OnSystemValueChanged();
                        InvalidateResources(true); // Invalidate all resource since this should happen only once
 
                        // NOTICE-2005/06/17-WAYNEZEN,
                        // We have to invoke the below method after InvalidateResources. 
                        // So the tablet ink HighContrastHelper can pick up the correct HighContrast setting. 
                        HighContrastHelper.OnSettingChanged();
                    } 
                    break;

                case NativeMethods.WM_TABLET_ADDED:
                    InvalidateTabletDevices(msg, wParam, lParam); 
                    break;
 
                case NativeMethods.WM_TABLET_REMOVED: 
                    InvalidateTabletDevices(msg, wParam, lParam);
                    break; 

            }

            return IntPtr.Zero ; 

        } 
 
        internal static bool ClearBitArray(BitArray cacheValid)
        { 
            bool changed = false;

            for (int i = 0; i < cacheValid.Count; i++)
            { 
                if (ClearSlot(cacheValid, i))
                { 
                    changed = true; 
                }
            } 

            return changed;
        }
 
        internal static bool ClearSlot(BitArray cacheValid, int slot)
        { 
            if (cacheValid[slot]) 
            {
                cacheValid[slot] = false; 
                return true;
            }

            return false; 
        }
 
        #endregion 

        // Flag the parser to create DeferredThemeReferences for thread safety 
        internal static bool IsSystemResourcesParsing
        {
            get
            { 
                return _parsing > 0;
            } 
            set 
            {
                if (value) 
                {
                    _parsing++;
                }
                else 
                {
                    _parsing--; 
                } 
            }
        } 

        // This is the lock used to protect access to the
        // theme dictionaries and the associated cache.
        internal static object ThemeDictionaryLock 
        {
            get { return _resourceCache.SyncRoot; } 
        } 

        #endregion 

        #region Data

        [ThreadStatic] private static int _parsing; 

        [ThreadStatic] private static SecurityCriticalDataClass _hwndNotify; 
        [ThreadStatic] [SecurityCritical] private static HwndWrapperHook _hwndNotifyHook; 

        private static Hashtable _resourceCache = new Hashtable(); 
        private static DTypeMap _themeStyleCache = new DTypeMap(100); // This is based upon the max DType.ID found in MSN scenario
        private static Dictionary _dictionaries;
        private static object _specialNull = new object();
 
        private const string GenericResourceName = "themes/generic";
        private const string ClassicResourceName = "themes/classic"; 
 
        private static Assembly _mscorlib;
        private static Assembly _presentationFramework; 
        private static Assembly _presentationCore;
        private static Assembly _windowsBase;
        internal const string PresentationFrameworkName = "PresentationFramework";
 
        // SystemResourcesHaveChanged indicates to FE that the font properties need to be coerced
        // when creating a new root element 
        internal static bool SystemResourcesHaveChanged; 

        // SystemResourcesAreChanging is used by FE when coercing the font properties to determine 
        // if it should return the current system metric or the value passed to the coerce callback
        [ThreadStatic]
        internal static bool SystemResourcesAreChanging;
        #endregion 
    }
 
    internal class DeferredResourceReference : DeferredReference 
    {
        #region Constructor 

        internal DeferredResourceReference(ResourceDictionary dictionary, object key)
        {
            _dictionary = dictionary; 
            _keyOrValue = key;
        } 
 
        #endregion Constructor
 
        #region Methods

        internal override object GetValue(BaseValueSourceInternal valueSource)
        { 
            // If the _value cache is invalid fetch the value from
            // the dictionary else just retun the cached value 
            if (_dictionary != null) 
            {
                bool canCache; 
                object value  = _dictionary.GetValue(_keyOrValue, out canCache);
                if (!CheckIfShared || canCache)
                {
                    // Note that we are replacing the _keyorValue field 
                    // with the value and nuking the _dictionary field.
                    _keyOrValue = value; 
                    RemoveFromDictionary(); 
                }
 
                // Freeze if this value originated from a style or template
                bool freezeIfPossible =
                    valueSource == BaseValueSourceInternal.ThemeStyle ||
                    valueSource == BaseValueSourceInternal.ThemeStyleTrigger || 
                    valueSource == BaseValueSourceInternal.Style ||
                    valueSource == BaseValueSourceInternal.TemplateTrigger || 
                    valueSource == BaseValueSourceInternal.StyleTrigger || 
                    valueSource == BaseValueSourceInternal.ParentTemplate ||
                    valueSource == BaseValueSourceInternal.ParentTemplateTrigger; 

                // This is to freeze values produced by deferred
                // references within styles and templates
                if (freezeIfPossible) 
                {
                    StyleHelper.SealIfSealable(value); 
                } 

                // tell any listeners (e.g. ResourceReferenceExpressions) 
                // that the value has been inflated
                if (Inflated != null)
                {
                    Inflated(this, EventArgs.Empty); 
                }
 
                return value; 
            }
 
            return _keyOrValue;
        }

        // Gets the type of the value it represents 
        internal override Type GetValueType()
        { 
            if (_dictionary != null) 
            {
                // Take a peek at the element type of the ElementStartRecord 
                // within the ResourceDictionary's deferred content.
                bool found;
                return _dictionary.GetValueType(_keyOrValue, out found);
            } 
            else
            { 
                return _keyOrValue != null ? _keyOrValue.GetType() : null; 
            }
        } 

        // remove this DeferredResourceReference from its ResourceDictionary
        internal virtual void RemoveFromDictionary()
        { 
            if (_dictionary != null)
            { 
                _dictionary.DeferredResourceReferences.Remove(this); 
                _dictionary = null;
            } 
        }

        #endregion Methods
 
        #region Properties
 
        internal virtual object Key 
        {
            get { return _keyOrValue; } 
        }

        internal ResourceDictionary Dictionary
        { 
            get { return _dictionary; }
            set { _dictionary = value; } 
        } 

        internal virtual object Value 
        {
            get { return _keyOrValue; }
            set { _keyOrValue = value; }
        } 

        internal virtual bool IsUnset 
        { 
            get { return false; }
        } 

        internal bool IsInflated
        {
            get { return (_dictionary == null); } 
        }
 
        internal bool CheckIfShared 
        {
            get { return _checkIfShared; } 
            set { _checkIfShared = value; }
        }

        #endregion Properties 

        #region Events 
 
        internal event EventHandler Inflated;
 
        #endregion Events

        #region Data
 
        private ResourceDictionary _dictionary;
        protected object _keyOrValue; 
        private bool _checkIfShared; 

        #endregion Data 
    }

    internal class DeferredAppResourceReference : DeferredResourceReference
    { 
        #region Constructor
 
        internal DeferredAppResourceReference(ResourceDictionary dictionary, object resourceKey) 
            : base(dictionary, resourceKey)
        { 
        }

        #endregion Constructor
 
        #region Methods
 
        internal override object GetValue(BaseValueSourceInternal valueSource) 
        {
            lock (((ICollection)Application.Current.Resources).SyncRoot) 
            {
                return base.GetValue(valueSource);
            }
        } 

        // Gets the type of the value it represents 
        internal override Type GetValueType() 
        {
            lock (((ICollection)Application.Current.Resources).SyncRoot) 
            {
                return base.GetValueType();
            }
        } 

        #endregion Methods 
    } 

    internal class DeferredThemeResourceReference : DeferredResourceReference 
    {
        #region Constructor

        internal DeferredThemeResourceReference(ResourceDictionary dictionary, object resourceKey) 
            :base(dictionary, resourceKey)
        { 
        } 

        #endregion Constructor 

        #region Methods

        internal override object GetValue(BaseValueSourceInternal valueSource) 
        {
            lock (SystemResources.ThemeDictionaryLock) 
            { 
                // If the value cache is invalid fetch the value from
                // the dictionary else just retun the cached value 
                if (Dictionary != null)
                {
                    bool canCache;
                    object key = Key; 
                    object value;
 
                    SystemResources.IsSystemResourcesParsing = true; 

                    try 
                    {
                        value = Dictionary.GetValue(key, out canCache);
                        if (!CheckIfShared || canCache)
                        { 
                            // Note that we are replacing the _keyorValue field
                            // with the value and nuking the _dictionary field. 
                            Value = value; 
                            Dictionary = null;
                        } 
                    }
                    finally
                    {
                        SystemResources.IsSystemResourcesParsing = false; 
                    }
 
                    // Only cache keys that would be located by FindResourceInternal 
                    if ((key is Type || key is ResourceKey) && canCache)
                    { 
                        SystemResources.CacheResource(key, value, false /*isTraceEnabled*/);
                    }

                    return value; 
                }
 
                return Value; 
            }
        } 

        // Gets the type of the value it represents
        internal override Type GetValueType()
        { 
            lock (SystemResources.ThemeDictionaryLock)
            { 
                return base.GetValueType(); 
            }
        } 

        // remove this DeferredResourceReference from its ResourceDictionary
        internal override void RemoveFromDictionary()
        { 
            // DeferredThemeResourceReferences are never added to the dictionary's
            // list of deferred references, so they don't need to be removed. 
        } 

        #endregion Methods 
    }

    /// 
    /// This signifies a DeferredResourceReference that is used as a place holder 
    /// for the front loaded StaticResource within a deferred content section.
    ///  
    internal class DeferredResourceReferenceHolder : DeferredResourceReference 
    {
        #region Constructor 

        internal DeferredResourceReferenceHolder(object resourceKey, object value)
            :base(null, null)
        { 
            _keyOrValue = new object[]{resourceKey, value};
        } 
 
        #endregion Constructor
 
        #region Methods

        internal override object GetValue(BaseValueSourceInternal valueSource)
        { 
            return Value;
        } 
 
        // Gets the type of the value it represents
        internal override Type GetValueType() 
        {
            object value = Value;
            return value != null ? value.GetType() : null;
        } 

        #endregion Methods 
 
        #region Properties
 
        internal override object Key
        {
            get { return ((object[])_keyOrValue)[0]; }
        } 

        internal override object Value 
        { 
            get { return ((object[])_keyOrValue)[1]; }
            set { ((object[])_keyOrValue)[1] = value; } 
        }

        internal override bool IsUnset
        { 
            get { return Value == DependencyProperty.UnsetValue; }
        } 
 
        #endregion Properties
    } 

}

 

 

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