Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@
<Compile Include="$(WpfSharedDir)\MS\Internal\ResourceIDHelper.cs">
<Link>Shared\MS\Internal\ResourceIDHelper.cs</Link>
</Compile>
<Compile Include="$(WpfSharedDir)\MS\Internal\ReflectionUtils.cs">
<Link>Shared\MS\Internal\ReflectionUtils.cs</Link>
</Compile>
<Compile Include="$(WpfSharedDir)\MS\Internal\SecurityHelper.cs">
<Link>Shared\MS\Internal\SecurityHelper.cs</Link>
</Compile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,8 +355,8 @@ private Stream GetCompositeFontResourceStream()
{
string fontFilename = _fontUri.OriginalString.Substring(_fontUri.OriginalString.LastIndexOf('/') + 1).ToLowerInvariant();

var fontResourceAssembly = Assembly.GetExecutingAssembly();
ResourceManager rm = new ResourceManager($"{fontResourceAssembly.GetName().Name}.g", fontResourceAssembly);
Assembly fontResourceAssembly = Assembly.GetExecutingAssembly();
ResourceManager rm = new($"{ReflectionUtils.GetAssemblyPartialName(fontResourceAssembly)}.g", fontResourceAssembly);

return rm?.GetStream($"fonts/{fontFilename}");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,10 @@ private ResourceSet ResourceSet
{
if (_resourceSet == null)
{
string manifestResourceName;
//"$(AssemblyShortname).unlocalizable.g"
string manifestResourceName = $"{ReflectionUtils.GetAssemblyPartialName(_assembly)}{UnLocalizableResourceNameSuffix}";
ResourceManager manager = new(manifestResourceName, _assembly);

manifestResourceName = SafeSecurityHelper.GetAssemblyPartialName(_assembly) + UnLocalizableResourceNameSuffix;

ResourceManager manager = new ResourceManager(manifestResourceName, this._assembly);
_resourceSet = manager.GetResourceSet(CultureInfo.InvariantCulture, true, false);
}

Expand All @@ -254,11 +253,9 @@ private ResourceManager ResourceManager
{
if (_resourceManager == null)
{
string baseResourceName; // Our build system always generate a resource base name "$(AssemblyShortname).g"

baseResourceName = SafeSecurityHelper.GetAssemblyPartialName(_assembly) + LocalizableResourceNameSuffix;

_resourceManager = new ResourceManager(baseResourceName, this._assembly);
// Our build system always generate a resource base name "$(AssemblyShortname).g"
string baseResourceName = $"{ReflectionUtils.GetAssemblyPartialName(_assembly)}{LocalizableResourceNameSuffix}";
_resourceManager = new ResourceManager(baseResourceName, _assembly);
}

return _resourceManager;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using MS.Win32;
using System.Windows.Input;
using System.Reflection;
using MS.Internal;
using MS.Win32;

namespace System.Windows.Interop
{
Expand Down Expand Up @@ -418,7 +419,7 @@ internal static bool PlatformSupportsTransparentChildWindows
/// <remarks>Not intended to be tested outside test code</remarks>
internal static void SetPlatformSupportsTransparentChildWindowsForTestingOnly(bool value)
{
if (string.Equals(System.Reflection.Assembly.GetEntryAssembly().GetName().Name, "drthwndsource", StringComparison.CurrentCultureIgnoreCase))
if (ReflectionUtils.GetAssemblyPartialName(Assembly.GetEntryAssembly()).Equals("drthwndsource", StringComparison.CurrentCultureIgnoreCase))
{
_platformSupportsTransparentChildWindows = value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ static internal bool IsComponentEntryAssembly(string component)

if (assembly != null)
{
return (string.Equals(SafeSecurityHelper.GetAssemblyPartialName(assembly), assemblyName, StringComparison.OrdinalIgnoreCase));
return ReflectionUtils.GetAssemblyPartialName(assembly).Equals(assemblyName, StringComparison.OrdinalIgnoreCase);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ static DocumentsTrace()
public DocumentsTrace(string switchName)
{
#if DEBUG
string name = SafeSecurityHelper.GetAssemblyPartialName( Assembly.GetCallingAssembly() );
_switch = new BooleanSwitch(switchName, $"[{name}]");
ReadOnlySpan<char> shortAssemblyName = ReflectionUtils.GetAssemblyPartialName(Assembly.GetCallingAssembly());
_switch = new BooleanSwitch(switchName, $"[{shortAssemblyName}]");
#endif
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using System.Globalization;
using XamlReaderHelper = System.Windows.Markup.XamlReaderHelper;
using System.Runtime.CompilerServices;
using MS.Internal;

namespace System.Windows.Baml2006
{
Expand Down Expand Up @@ -2105,11 +2106,9 @@ private string Logic_GetFullXmlns(string uriInput)

// Providing the assembly short name may lead to ambiguity between two versions of the same assembly, but we need to
// keep it this way since it is exposed publicly via the Namespace property, Baml2006ReaderInternal provides the full Assembly name.
// We need to avoid Assembly.GetName() so we run in PartialTrust without asserting.
internal virtual ReadOnlySpan<char> GetAssemblyNameForNamespace(Assembly assembly)
{
string assemblyLongName = assembly.FullName;
return assemblyLongName.AsSpan(0, assemblyLongName.IndexOf(','));
return ReflectionUtils.GetAssemblyPartialName(assembly);
}

// (prefix, namespaceUri)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ internal Baml2006ReaderInternal(
#endregion

// Return the full assembly name, this includes the assembly version
internal override ReadOnlySpan<char> GetAssemblyNameForNamespace(Assembly asm)
internal override ReadOnlySpan<char> GetAssemblyNameForNamespace(Assembly assembly)
{
return asm.FullName;
return assembly.FullName;
}

// When processing ResourceDictionary.Source we may find a Uri that references the
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

//
// Contents: XAML writer
//

using System.Xml.Serialization;
using System.ComponentModel;
using System.Reflection;
using System.Collections;
using System.Reflection;
using MS.Internal;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace System.Windows.Markup.Primitives
{
Expand Down Expand Up @@ -1610,14 +1610,14 @@ public static string GetNamespaceUriFor(Type type)
{
if (type.Namespace == null)
{
result = $"{clrUriPrefix};assembly={type.Assembly.GetName().Name}";
result = $"{clrUriPrefix};assembly={ReflectionUtils.GetAssemblyPartialName(type.Assembly)}";
}
else
{
Dictionary<string, string> namespaceToUri = GetMappingsFor(type.Assembly);
if (!namespaceToUri.TryGetValue(type.Namespace, out result))
{
result = $"{clrUriPrefix}{type.Namespace};assembly={type.Assembly.GetName().Name}";
result = $"{clrUriPrefix}{type.Namespace};assembly={ReflectionUtils.GetAssemblyPartialName(type.Assembly)}";
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2481,7 +2481,7 @@ private static bool IsFriendAssembly(Assembly assembly)

private static bool IsInternalAllowedOnType(Type type)
{
bool isInternalAllowed = ReflectionHelper.LocalAssemblyName == type.Assembly.GetName().Name ||
bool isInternalAllowed = ReflectionHelper.LocalAssemblyName == ReflectionUtils.GetAssemblyPartialName(type.Assembly) ||
IsFriendAssembly(type.Assembly);
_hasInternals = _hasInternals || isInternalAllowed;
return isInternalAllowed;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ internal ResourceDictionaries(Assembly assembly)
}
else
{
_assemblyName = SafeSecurityHelper.GetAssemblyPartialName(assembly);
_assemblyName = ReflectionUtils.GetAssemblyPartialName(assembly).ToString();
}
}

Expand Down Expand Up @@ -786,7 +786,7 @@ private void LoadExternalAssembly(bool classic, bool generic, out Assembly assem
}

assemblyName = sb.ToString();
string fullName = SafeSecurityHelper.GetFullAssemblyNameFromPartialName(_assembly, assemblyName);
string fullName = ReflectionUtils.GetFullAssemblyNameFromPartialName(_assembly, assemblyName);

assembly = null;
try
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable enable

using System.Runtime.CompilerServices;
using System.Reflection.Metadata;
using System.Reflection;
using System;

namespace MS.Internal
{
/// <summary>
/// Provides utilities for working with reflection efficiently.
/// </summary>
internal static class ReflectionUtils
{
#if !NETFX
/// <summary>
/// Retrieves the full assembly name by combining the <paramref name="partialName"/> passed in
/// with everything else from <paramref name="assembly"/>.
/// </summary>
internal static string GetFullAssemblyNameFromPartialName(Assembly assembly, string partialName)
{
ArgumentNullException.ThrowIfNull(assembly, nameof(assembly));
string? fullName = assembly.FullName;
ArgumentNullException.ThrowIfNull(fullName, nameof(Assembly.FullName));

AssemblyName name = new(fullName) { Name = partialName };
return name.FullName;
}
#endif

/// <summary>
/// Given an <paramref name="assembly"/>, returns the partial/simple name of the assembly.
/// </summary>
#if !NETFX
internal static ReadOnlySpan<char> GetAssemblyPartialName(Assembly assembly)
#else
internal static string GetAssemblyPartialName(Assembly assembly)
#endif
{
#if !NETFX
ArgumentNullException.ThrowIfNull(assembly, nameof(assembly));
// We know that the input is trusted (it will be properly escaped, with ", " between tokens etc.)
// So we can allow ourselves to do a little trick, where we just find the first separator
// You cannot load an assembly (or define) where name is empty, it needs to be at least 1 character
// But we will keep this for consistency of the previous function, maybe I've missed a class
ReadOnlySpan<char> fullName = assembly.FullName;
if (fullName.IsEmpty)
return ReadOnlySpan<char>.Empty;

ReadOnlySpan<char> nameSlice = fullName;
// Skip any escaped commas in the name if present
int escapedComma = fullName.LastIndexOf("\\,", StringComparison.Ordinal);
if (escapedComma != -1)
nameSlice = nameSlice.Slice(escapedComma + 2);

// Find the real ending of the name section
int commaIndex = nameSlice.IndexOf(',');
if (commaIndex != -1)
fullName = fullName.Slice(0, fullName.Length - nameSlice.Length + commaIndex);

// Check if we need to unescape, this is very rare case so we can just do it the dirty way
if (escapedComma != -1 || fullName.Contains('\\'))
UnescapeDirty(ref fullName);

// Since having "," or "=" in the assembly name is very rare, we don't want to inline
// and we will fallback to the runtime implementation to handle such case for us
[MethodImpl(MethodImplOptions.NoInlining)]
static void UnescapeDirty(ref ReadOnlySpan<char> dirtyName)
{
dirtyName = !AssemblyNameInfo.TryParse(dirtyName, out AssemblyNameInfo? result) ? ReadOnlySpan<char>.Empty : result.Name;
}

return fullName;
#else
AssemblyName name = new(assembly.FullName);
return name.Name ?? string.Empty;
#endif
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,39 +58,7 @@ internal static void TransformLocalRectToScreen(HandleRef hwnd, ref NativeMethod
}
#endif

#if PRESENTATION_CORE || PRESENTATIONFRAMEWORK ||REACHFRAMEWORK || DEBUG

#if !WINDOWS_BASE && !SYSTEM_XAML
/// <summary>
/// Given an assembly, returns the partial name of the assembly.
/// </summary>
internal static string GetAssemblyPartialName(Assembly assembly)
{
AssemblyName name = new AssemblyName(assembly.FullName);
string partialName = name.Name;
return partialName ?? string.Empty;
}
#endif

#endif

#if PRESENTATIONFRAMEWORK

/// <summary>
/// Get the full assembly name by combining the partial name passed in
/// with everything else from proto assembly.
/// </summary>
internal static string GetFullAssemblyNameFromPartialName(
Assembly protoAssembly,
string partialName)
{
AssemblyName name = new AssemblyName(protoAssembly.FullName)
{
Name = partialName
};
return name.FullName;
}

internal static Point ClientToScreen(UIElement relativeTo, Point point)
{
GeneralTransform transform;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ internal static bool IsFriendAssembly(Assembly sourceAssembly)
#if PBTCOMPILER
internal static bool IsInternalAllowedOnType(Type type)
{
return ((LocalAssemblyName == type.Assembly.GetName().Name) || IsFriendAssembly(type.Assembly));
return LocalAssemblyName == ReflectionUtils.GetAssemblyPartialName(type.Assembly) || IsFriendAssembly(type.Assembly);
}
#endif

Expand Down
3 changes: 3 additions & 0 deletions src/Microsoft.DotNet.Wpf/src/System.Xaml/System.Xaml.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
<Compile Include="$(WpfSharedDir)MS\Internal\Xaml\Parser\SpecialBracketCharacters.cs">
<Link>Common\WPF\MS\Internal\Xaml\Parser\SpecialBracketCharacters.cs</Link>
</Compile>
<Compile Include="$(WpfSharedDir)\MS\Internal\ReflectionUtils.cs">
<Link>Common\WPF\MS\Internal\ReflectionUtils.cs</Link>
</Compile>
<Compile Include="$(WpfSharedDir)MS\Internal\SafeSecurityHelper.cs">
<Link>Common\WPF\MS\Internal\SafeSecurityHelper.cs</Link>
</Compile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
using System.Windows.Markup;
using System.Xaml.Schema;

using MS.Internal;

namespace System.Xaml.MS.Impl
{
class XmlNsInfo
Expand Down Expand Up @@ -223,8 +225,7 @@ ConcurrentDictionary<string, IList<string>> LoadClrToXmlNs()
xmlNamespaceList.Add(nsDef.XmlNamespace);
}

string assemblyName = _fullyQualifyAssemblyName ?
assembly.FullName : XamlSchemaContext.GetAssemblyShortName(assembly);
string assemblyName = _fullyQualifyAssemblyName ? assembly.FullName : ReflectionUtils.GetAssemblyPartialName(assembly).ToString();
foreach (KeyValuePair<string, IList<string>> clrToXmlNs in result)
{
// Sort namespaces in preference order
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Collections.ObjectModel;
using System.Reflection;
using System.Text;
using MS.Internal;
using System.Threading;
using System.Xaml.MS.Impl;
using System.Xaml.Schema;
Expand Down Expand Up @@ -786,7 +787,6 @@ internal bool AreInternalsVisibleTo(Assembly fromAssembly, Assembly toAssembly)
return false;
}

// Not using Assembly.GetName() because it doesn't work in partial-trust
AssemblyName toAssemblyName = new AssemblyName(toAssembly.FullName);
foreach (AssemblyName friend in friends)
{
Expand Down Expand Up @@ -1042,8 +1042,7 @@ private ReadOnlyCollection<string> GetXmlNsMappings(Assembly assembly, string cl

if (!assemblyMappings.TryGetValue(clrNs, out result))
{
string assemblyName = FullyQualifyAssemblyNamesInClrNamespaces ?
assembly.FullName : GetAssemblyShortName(assembly);
string assemblyName = FullyQualifyAssemblyNamesInClrNamespaces ? assembly.FullName : ReflectionUtils.GetAssemblyPartialName(assembly).ToString();
string xmlns = ClrNamespaceUriParser.GetUri(clrNs, assemblyName);
List<string> list = new List<string>();
list.Add(xmlns);
Expand Down Expand Up @@ -1202,14 +1201,6 @@ bool UpdateNamespaceByUriList(XmlNsInfo nsInfo)

#region Helper Methods

// Given an assembly, return the assembly short name. We need to avoid Assembly.GetName() so we run in PartialTrust without asserting.
internal static string GetAssemblyShortName(Assembly assembly)
{
string assemblyLongName = assembly.FullName;
string assemblyShortName = assemblyLongName.Substring(0, assemblyLongName.IndexOf(','));
return assemblyShortName;
}

internal static ConcurrentDictionary<K, V> CreateDictionary<K, V>()
{
return new ConcurrentDictionary<K, V>(ConcurrencyLevel, DictionaryCapacity);
Expand Down
Loading