Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Runtime.InteropServices;

internal static partial class Interop
{
internal static partial class CoreFoundation
{
internal const uint kCFStringEncodingUTF8 = 0x08000100;

[LibraryImport(Libraries.CoreFoundationLibrary)]
internal static partial IntPtr CFBundleGetIdentifier(IntPtr bundle);

[LibraryImport(Libraries.CoreFoundationLibrary)]
internal static partial IntPtr CFBundleGetMainBundle();

[LibraryImport(Libraries.CoreFoundationLibrary)]
internal static unsafe partial byte CFStringGetCString(
IntPtr value,
byte* buffer,
IntPtr bufferSize,
uint encoding);

[LibraryImport(Libraries.CoreFoundationLibrary)]
internal static partial IntPtr CFStringGetLength(IntPtr value);

[LibraryImport(Libraries.CoreFoundationLibrary)]
internal static partial IntPtr CFStringGetMaximumSizeForEncoding(IntPtr length, uint encoding);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.InteropServices;

internal static partial class Interop
{
internal static partial class Kernel32
{
[LibraryImport(Libraries.Kernel32)]
internal static unsafe partial int GetCurrentPackageFamilyName(uint* packageFamilyNameLength, char* packageFamilyName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

internal static partial class Interop
{
internal static partial class Libraries
{
internal const string CoreFoundationLibrary = "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation";
internal const string Kernel32 = "kernel32.dll";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
</PropertyGroup>

<ItemGroup Condition="'$(IsPartialFacadeAssembly)' != 'true'">
<Compile Include="Interop\Interop.Libraries.cs" />
<Compile Include="$(CommonPath)Interop\OSX\Interop.CoreFoundation.CFBundle.cs" Link="Interop\OSX\Interop.CoreFoundation.CFBundle.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentPackageFamilyName.cs" Link="Interop\Windows\Kernel32\Interop.GetCurrentPackageFamilyName.cs" />
<Compile Include="System\Configuration\AppleApplication.cs" />
<Compile Include="System\Configuration\DictionarySectionHandler.cs" />
<Compile Include="System\Configuration\DpapiProtectedConfigurationProvider.cs" />
<Compile Include="System\Configuration\IConfigurationSystem.cs" />
Expand Down Expand Up @@ -249,6 +253,7 @@
<Compile Include="System\Configuration\ValidatorCallback.cs" />
<Compile Include="System\Configuration\ValidatorUtils.cs" />
<Compile Include="System\Configuration\WhiteSpaceTrimStringConverter.cs" />
<Compile Include="System\Configuration\WindowsApplication.cs" />
<Compile Include="System\Configuration\XmlUtil.cs" />
<Compile Include="System\Configuration\XmlUtilWriter.cs" />
<Compile Include="System\Drawing\Configuration\SystemDrawingSection.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Text;

namespace System.Configuration
{
internal static class AppleApplication
{
internal static unsafe string GetMainBundleIdentifier()
{
IntPtr bundle = Interop.CoreFoundation.CFBundleGetMainBundle();
IntPtr identifier = bundle == IntPtr.Zero
? IntPtr.Zero
: Interop.CoreFoundation.CFBundleGetIdentifier(bundle);
if (identifier == IntPtr.Zero)
{
return null;
}

IntPtr length = Interop.CoreFoundation.CFStringGetLength(identifier);
long maximumByteCount = Interop.CoreFoundation.CFStringGetMaximumSizeForEncoding(
length,
Interop.CoreFoundation.kCFStringEncodingUTF8).ToInt64();
if (maximumByteCount < 0 || maximumByteCount >= int.MaxValue)
{
return null;
}

byte[] buffer = new byte[(int)maximumByteCount + 1];
fixed (byte* bufferPtr = buffer)
{
if (Interop.CoreFoundation.CFStringGetCString(
identifier,
bufferPtr,
new IntPtr(buffer.Length),
Interop.CoreFoundation.kCFStringEncodingUTF8) == 0)
{
return null;
}
}

int terminator = Array.IndexOf(buffer, (byte)0);
if (terminator < 0)
{
return null;
}

return Encoding.UTF8.GetString(buffer, 0, terminator);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ internal sealed class ClientConfigPaths
private const string StrongNameDesc = "StrongName";
private const string UrlDesc = "Url";
private const string PathDesc = "Path";
private const string BundleIdentifierDesc = "BundleIdentifier";
private const string PackageFamilyNameDesc = "PackageFamilyName";

private static ClientConfigPaths s_current;
private static volatile bool s_currentIncludesUserConfig;
Expand Down Expand Up @@ -142,10 +144,22 @@ private ClientConfigPaths(string exePath, bool includeUserConfig)
string applicationUriLower = !string.IsNullOrEmpty(ApplicationUri)
? ApplicationUri.ToLowerInvariant()
: null;
string hashSuffix = GetTypeAndHashSuffix(applicationUriLower, isSingleFile);
GetStableApplicationIdentity(out string stableIdentityType, out string stableIdentity);
string hashSuffix = GetApplicationIdentitySuffix(
applicationUriLower,
isSingleFile,
stableIdentityType,
stableIdentity);
string part2 = !string.IsNullOrEmpty(namePrefix) && !string.IsNullOrEmpty(hashSuffix)
? namePrefix + hashSuffix
: null;
LegacyConfigDirectoryPrefix = !string.IsNullOrEmpty(stableIdentity) &&
!string.IsNullOrEmpty(namePrefix)
? namePrefix + "_"
: null;
StableConfigDirectoryName = LegacyConfigDirectoryPrefix is not null
? part2
: null;

// (3) The product version
string part3 = Validate(ProductVersion, limitSize: false);
Expand Down Expand Up @@ -191,6 +205,10 @@ private ClientConfigPaths(string exePath, bool includeUserConfig)

internal string ProductVersion { get; private set; }

internal string LegacyConfigDirectoryPrefix { get; }

internal string StableConfigDirectoryName { get; }

internal static ClientConfigPaths GetPaths(string exePath, bool includeUserConfig)
{
ClientConfigPaths result;
Expand Down Expand Up @@ -231,6 +249,58 @@ private static string CombineIfValid(string path1, string path2)
}
}

internal static string GetApplicationIdentitySuffix(
string exePath,
bool isSingleFile,
string stableIdentityType,
string stableIdentity)
{
if (!string.IsNullOrEmpty(stableIdentityType) && !string.IsNullOrEmpty(stableIdentity))
{
try
{
string hash = IdentityHelper.GetStrongHashSuitableForObjectName(stableIdentity);
return "_" + stableIdentityType + "_" + hash;
}
catch (PlatformNotSupportedException)
{
}
}

return GetTypeAndHashSuffix(exePath, isSingleFile);
}

private static void GetStableApplicationIdentity(out string identityType, out string identity)
{
if (IsAlwaysSandboxedAppleMobile())
{
identityType = BundleIdentifierDesc;
identity = AppleApplication.GetMainBundleIdentifier();
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
identityType = PackageFamilyNameDesc;
try
{
identity = WindowsApplication.GetCurrentPackageFamilyName();
}
catch (EntryPointNotFoundException)
{
identity = null;
}
}
else
{
identityType = null;
identity = null;
}

if (string.IsNullOrEmpty(identity))
{
identityType = null;
}
}

// Returns a type and hash suffix based on what used to come from app domain evidence.
// The evidence we use, in priority order, is Strong Name, Url and Exe Path. If one of
// these is found, we compute a SHA1 hash of it and return a suffix based on that.
Expand Down Expand Up @@ -287,6 +357,13 @@ private static string GetTypeAndHashSuffix(string exePath, bool isSingleFile)
return suffix;
}

private static bool IsAlwaysSandboxedAppleMobile()
{
return RuntimeInformation.IsOSPlatform(OSPlatform.Create("TVOS")) ||
(RuntimeInformation.IsOSPlatform(OSPlatform.Create("IOS")) &&
!RuntimeInformation.IsOSPlatform(OSPlatform.Create("MACCATALYST")));
}

private void SetNamesAndVersion(Assembly exeAssembly, bool isHttp)
{
Type mainType = null;
Expand Down
Loading
Loading