/****************************************************************************\
*
* File: SafeSecurityHelper.cs
*
* Purpose: Helper functions that require elevation but are safe to use.
*
* History:
* 10/15/04: [....] Created
*
* Copyright (C) 2004 by Microsoft Corporation. All rights reserved.
*
\***************************************************************************/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Security;
using System.Security.Permissions;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
#if SYSTEM_XAML
using TypeConverterHelper = System.Xaml.TypeConverterHelper;
#else
using Microsoft.Win32;
using MS.Win32;
using TypeConverterHelper = System.Windows.Markup.TypeConverterHelper;
#endif
#if PRESENTATIONFRAMEWORK
using System.Windows;
using System.Windows.Media;
#endif
// The SafeSecurityHelper class differs between assemblies and could not actually be
// shared, so it is duplicated across namespaces to prevent name collision.
#if WINDOWS_BASE
namespace MS.Internal.WindowsBase
#elif PRESENTATION_CORE
namespace MS.Internal.PresentationCore
#elif PRESENTATIONFRAMEWORK
namespace MS.Internal.PresentationFramework
#elif REACHFRAMEWORK
namespace MS.Internal.ReachFramework
#elif DRT
namespace MS.Internal.Drt
#elif SYSTEM_XAML
namespace System.Xaml
#else
#error Class is being used from an unknown assembly.
#endif
{
internal static partial class SafeSecurityHelper
{
#if PRESENTATION_CORE
///
/// Given a rectangle with coords in local screen coordinates.
/// Return the rectangle in global screen coordinates.
///
///
/// Critical - calls a critical function.
/// TreatAsSafe - handing out a transformed rect is considered safe.
///
/// Although we are calling a function that passes an array, and no. of elements.
/// We limit this call to only call this function with a 2 as the count of elements.
/// Thereby containing any potential for the call to Win32 to cause a buffer overrun.
///
[SecurityCritical, SecurityTreatAsSafe ]
internal static void TransformLocalRectToScreen(HandleRef hwnd, ref NativeMethods.RECT rcWindowCoords)
{
int retval = MapWindowPoints(hwnd , new HandleRef(null, IntPtr.Zero), ref rcWindowCoords, 2);
int win32Err = Marshal.GetLastWin32Error();
if(retval == 0 && win32Err != 0)
{
throw new System.ComponentModel.Win32Exception(win32Err);
}
}
#endif
#if PRESENTATION_CORE || PRESENTATIONFRAMEWORK ||REACHFRAMEWORK || DEBUG
#if !WINDOWS_BASE && !SYSTEM_XAML
///
/// Given an assembly, returns the partial name of the assembly.
///
///
/// This code used to perform an elevation but no longer needs to.
/// The method is being kept in this class to ease auditing and
/// should have a security review if changed.
/// The string returned does not contain path information.
/// This code is duplicated in SafeSecurityHelperPBT.cs.
///
internal static string GetAssemblyPartialName(Assembly assembly)
{
AssemblyName name = new AssemblyName(assembly.FullName);
string partialName = name.Name;
return (partialName != null) ? partialName : String.Empty;
}
#endif
#endif
#if PRESENTATIONFRAMEWORK
///
/// Get the full assembly name by combining the partial name passed in
/// with everything else from proto assembly.
///
///
/// This code used to perform an elevation but no longer needs to.
/// The method is being kept in this class to ease auditing and
/// should have a security review if changed.
/// The string returned does not contain path information.
///
internal static string GetFullAssemblyNameFromPartialName(
Assembly protoAssembly,
string partialName)
{
AssemblyName name = new AssemblyName(protoAssembly.FullName);
name.Name = partialName;
return name.FullName;
}
///
/// Critical: This code accesses PresentationSource which is critical but does not
/// expose it.
/// TreatAsSafe: PresentationSource is not exposed and Client to Screen co-ordinates is
/// safe to expose
///
[SecurityCritical,SecurityTreatAsSafe]
internal static Point ClientToScreen(UIElement relativeTo, Point point)
{
GeneralTransform transform;
PresentationSource source = PresentationSource.CriticalFromVisual(relativeTo);
if (source == null)
{
return new Point(double.NaN, double.NaN);
}
transform = relativeTo.TransformToAncestor(source.RootVisual);
Point ptRoot;
transform.TryTransform(point, out ptRoot);
Point ptClient = PointUtil.RootToClient(ptRoot, source);
Point ptScreen = PointUtil.ClientToScreen(ptClient, source);
return ptScreen;
}
#endif // PRESENTATIONFRAMEWORK
#if WINDOWS_BASE || PRESENTATION_CORE || SYSTEM_XAML
// Cache of Assembly -> AssemblyName, because calling new AssemblyName() is expensive.
// If the assembly is static, the key is the assembly; if it's dynamic, the key is a WeakRefKey
// pointing to the assembly, so we don't root collectible assemblies.
//
// This cache is bound (gated) by the number of assemblies in the appdomain.
// We use a callback on GC to purge out collected assemblies, so we don't grow indefinitely.
//
static Dictionary