Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit bcc6edf

Browse files
committed
Using System.IO.Path from System.Runtime.Extensions in CoreCLR
Today on CoreCLR we use the System.IO.Path from mscorlib, type forwarded from System.Runtime.Extensions.dll. Today on .NET Native, we use the System.IO.Path from System.Runtime.Extensions.dll. As such, there’s a Path.cs file in corefx that goes unused on CoreCLR, which ends up using the Path.cs. This leads to a variety of problems. In particular, beyond the code duplication and the divergence between .NET Native and CoreCLR, we have a bunch of changes we need to make to Path in support of cross-platform execution. This change switches System.Runtime.Extensions to using its Path.cs rather than type forwarding to the Path in mscorlib. As part of that, I’ve introduced the same kind of managed PAL abstraction that we have elsewhere in corefx. In particular, we now have: - Path.cs – the main file included for all builds - Path.Unix.cs – included in Unix builds, augmenting Path.cs with Unix-specific implementations (note that the Path.Unix.cs file is currently mostly stubbed out, and as such this switch currently only applies to the Windows build. - Path.Windows.cs – included in Windows builds, augmenting Path.cs with Windows-specific implementations - Path.WinRT.cs – included in .NET Native builds, augmenting Path.Windows.cs with a small amount of WinRT-related functionality - Path.Win32.cs – included in CoreCLR builds, augmenting Path.Windows.cs with a small amount of additional Win32-related functionality The majority of the changes are just moving code around. Along the way, I did clean up a few minor things, like using “string” instead of “String”, changing Contract.Assert to Debug.Assert, fixing some out-of-date or misleading comments, and fixing a couple of string concatenations that were resulting in unnecessary allocations. [tfs-changeset: 1497148]
1 parent 9b16041 commit bcc6edf

17 files changed

+1051
-981
lines changed

src/Common/src/Interop/Windows/BCrypt/Interop.BCryptGenRandom.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
using System;
5+
using System.Diagnostics;
56
using System.Runtime.InteropServices;
67

78
internal partial class Interop
89
{
910
internal partial class BCrypt
1011
{
11-
internal static void BCryptGenRandom(byte[] buffer)
12+
internal static NTSTATUS BCryptGenRandom(byte[] pbBuffer, int cbBuffer)
1213
{
13-
NTSTATUS ntStatus = BCryptGenRandom(IntPtr.Zero, buffer, buffer.Length, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
14-
if (ntStatus != NTSTATUS.STATUS_SUCCESS)
15-
throw CreateCryptographicException(ntStatus);
14+
Debug.Assert(pbBuffer != null);
15+
Debug.Assert(cbBuffer >= 0 && cbBuffer <= pbBuffer.Length);
16+
17+
return BCryptGenRandom(IntPtr.Zero, pbBuffer, cbBuffer, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
1618
}
1719

1820
private const int BCRYPT_USE_SYSTEM_PREFERRED_RNG = 0x00000002;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Security.Cryptography;
6+
7+
internal partial class Interop
8+
{
9+
internal partial class BCrypt
10+
{
11+
internal static Exception CreateCryptographicException(NTSTATUS ntStatus)
12+
{
13+
int hr = ((int)ntStatus) | 0x01000000;
14+
return new CryptographicException(hr);
15+
}
16+
}
17+
}

src/Common/src/Interop/Windows/BCrypt/Interop.NTSTATUS.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,12 @@ internal partial class Interop
88
{
99
internal partial class BCrypt
1010
{
11-
private enum NTSTATUS : uint
11+
internal enum NTSTATUS : uint
1212
{
1313
STATUS_SUCCESS = 0x0,
1414
STATUS_NOT_FOUND = 0xc0000225,
1515
STATUS_INVALID_PARAMETER = 0xc000000d,
1616
STATUS_NO_MEMORY = 0xc0000017,
1717
}
18-
19-
private static Exception CreateCryptographicException(NTSTATUS ntStatus)
20-
{
21-
int hr = ((int)ntStatus) | 0x01000000;
22-
return new CryptographicException(hr);
23-
}
2418
}
2519
}

src/Common/src/Interop/Windows/Interop.Libraries.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ internal static class Libraries
99
internal const string Console_L1 = "api-ms-win-core-console-l1-1-0.dll";
1010
internal const string Console_L2 = "api-ms-win-core-console-l2-1-0.dll";
1111
internal const string CoreFile_L1 = "api-ms-win-core-file-l1-1-0.dll";
12+
internal const string CoreFile_L1_2 = "api-ms-win-core-file-l1-2-0.dll";
1213
internal const string CoreFile_L2 = "api-ms-win-core-file-l2-1-0.dll";
1314
internal const string Crypt32 = "crypt32.dll";
1415
internal const string Debug = "api-ms-win-core-debug-l1-1-0.dll";
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Runtime.InteropServices;
6+
using System.Text;
7+
8+
partial class Interop
9+
{
10+
partial class mincore
11+
{
12+
[DllImport(Libraries.CoreFile_L1, SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)]
13+
internal unsafe static extern int GetFullPathNameW(char* path, int numBufferChars, char* buffer, IntPtr mustBeZero);
14+
15+
[DllImport(Libraries.CoreFile_L1, SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)]
16+
internal static extern int GetFullPathNameW(string path, int numBufferChars, [Out]StringBuilder buffer, IntPtr mustBeZero);
17+
}
18+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System.Text;
5+
using System.Runtime.InteropServices;
6+
7+
partial class Interop
8+
{
9+
partial class mincore
10+
{
11+
[DllImport(Libraries.CoreFile_L1, SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)]
12+
internal unsafe static extern int GetLongPathNameW(char* path, char* longPathBuffer, int bufferLength);
13+
14+
[DllImport(Libraries.CoreFile_L1, SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)]
15+
internal static extern int GetLongPathNameW(string path, [Out]StringBuilder longPathBuffer, int bufferLength);
16+
}
17+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Text;
6+
using System.Runtime.InteropServices;
7+
8+
partial class Interop
9+
{
10+
partial class mincore
11+
{
12+
[DllImport(Libraries.CoreFile_L1, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false)]
13+
internal static extern uint GetTempFileNameW(string tmpPath, string prefix, uint uniqueIdOrZero, [Out]StringBuilder tmpFileName);
14+
}
15+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System.Text;
5+
using System.Runtime.InteropServices;
6+
7+
partial class Interop
8+
{
9+
partial class mincore
10+
{
11+
[DllImport(Libraries.CoreFile_L1_2, CharSet = CharSet.Unicode, BestFitMapping = false)]
12+
internal static extern uint GetTempPathW(int bufferLen, [Out]StringBuilder buffer);
13+
}
14+
}

src/System.Runtime.Extensions/src/System.Runtime.Extensions.CoreCLR.csproj

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
1010
<IsPartialFacadeAssembly>true</IsPartialFacadeAssembly>
1111
<NuGetTargetFrameworkMoniker>DNXCore,Version=v5.0</NuGetTargetFrameworkMoniker>
12+
<!-- System.IO.Path conflicts between type in partial facade and in mscorlib -->
13+
<NoWarn>0436</NoWarn>
1214
</PropertyGroup>
1315

1416
<!-- Default configurations to help VS understand the configurations -->
@@ -41,28 +43,49 @@
4143

4244
<ItemGroup Condition=" '$(TargetsWindows)' == 'true' ">
4345
<Compile Include="System\Diagnostics\Stopwatch.Windows.cs" />
46+
<Compile Include="System\IO\Path.cs" /> <!-- TODO: Move this to the common group once Path.Unix.cs is implemented -->
47+
<Compile Include="System\IO\Path.Windows.cs" />
48+
<Compile Include="System\IO\Path.Win32.cs" />
49+
<Compile Include="System\IO\PathHelper.Windows.cs" />
4450
<Compile Include="$(CommonPath)\System\IO\Win32Marshal.cs">
4551
<Link>System\IO\Win32Marshal.cs</Link>
4652
</Compile>
4753
<Compile Include="$(CommonPath)\Interop\Windows\Interop.Libraries.cs">
4854
<Link>Interop\Windows\Interop.Libraries.cs</Link>
4955
</Compile>
56+
<Compile Include="$(CommonPath)\Interop\Windows\BCrypt\Interop.BCryptGenRandom.cs">
57+
<Link>Common\Interop\Windows\BCrypt\Interop.BCryptGenRandom.cs</Link>
58+
</Compile>
59+
<Compile Include="$(CommonPath)\Interop\Windows\BCrypt\Interop.NTSTATUS.cs">
60+
<Link>Common\Interop\Windows\BCrypt\Interop.NTSTATUS.cs</Link>
61+
</Compile>
5062
<Compile Include="$(CommonPath)\Interop\Windows\mincore\Interop.Errors.cs">
5163
<Link>Interop\Windows\mincore\Interop.Errors.cs</Link>
5264
</Compile>
5365
<Compile Include="$(CommonPath)\Interop\Windows\mincore\Interop.FormatMessage.cs">
5466
<Link>Interop\Windows\mincore\Interop.FormatMessage.cs</Link>
5567
</Compile>
68+
<Compile Include="$(CommonPath)\Interop\Windows\mincore\Interop.GetFullPathNameW.cs">
69+
<Link>Interop\Windows\mincore\Interop.GetFullPathNameW.cs</Link>
70+
</Compile>
5671
<Compile Include="$(CommonPath)\Interop\Windows\mincore\Interop.GetLastError.cs">
5772
<Link>Interop\Windows\mincore\Interop.GetLastError.cs</Link>
5873
</Compile>
74+
<Compile Include="$(CommonPath)\Interop\Windows\mincore\Interop.GetLongPathNameW.cs">
75+
<Link>Interop\Windows\mincore\Interop.GetLongPathNameW.cs</Link>
76+
</Compile>
77+
<Compile Include="$(CommonPath)\Interop\Windows\mincore\Interop.GetTempFileNameW.cs">
78+
<Link>Interop\Windows\mincore\Interop.GetTempFileNameW.cs</Link>
79+
</Compile>
80+
<Compile Include="$(CommonPath)\Interop\Windows\mincore\Interop.GetTempPathW.cs">
81+
<Link>Interop\Windows\mincore\Interop.GetTempPathW.cs</Link>
82+
</Compile>
5983
<Compile Include="$(CommonPath)\Interop\Windows\mincore\Interop.QueryPerformanceCounter.cs">
6084
<Link>Interop\Windows\mincore\Interop.QueryPerformanceCounter.cs</Link>
6185
</Compile>
6286
<Compile Include="$(CommonPath)\Interop\Windows\mincore\Interop.QueryPerformanceFrequency.cs">
6387
<Link>Interop\Windows\mincore\Interop.QueryPerformanceFrequency.cs</Link>
6488
</Compile>
65-
6689
</ItemGroup>
6790

6891
<ItemGroup Condition=" '$(TargetsUnix)' == 'true' ">
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Diagnostics;
6+
7+
// TODO: This partial implementation is currently stubbed out and should not be
8+
// included in the .csproj until completed.
9+
10+
namespace System.IO
11+
{
12+
public static partial class Path
13+
{
14+
public static readonly char DirectorySeparatorChar = '/';
15+
public static readonly char VolumeSeparatorChar = '/';
16+
public static readonly char PathSeparator = ':';
17+
18+
private const string DirectorySeparatorCharAsString = "/";
19+
20+
private static readonly char[] RealInvalidPathChars = { '\0' };
21+
private static readonly char[] InvalidPathCharsWithAdditionalChecks = { '\0', '*', '?' }; // Used by HasIllegalCharacters
22+
private static readonly char[] InvalidFileNameChars = { '\0', '/' };
23+
24+
// TODO: Implement these values correctly (dynamically) for Unix
25+
private static readonly int MaxPath = 4096;
26+
private static readonly int MaxComponentLength = 255;
27+
28+
private static bool IsDirectorySeparator(char c)
29+
{
30+
// The alternatie directory separator char is the same as the directory separator,
31+
// so we only need to check one.
32+
Debug.Assert(DirectorySeparatorChar == AltDirectorySeparatorChar);
33+
return c == DirectorySeparatorChar;
34+
}
35+
36+
private static bool IsDirectoryOrVolumeSeparator(char c)
37+
{
38+
// The directory separator is the same as the volume separator,
39+
// so we only need to check one.
40+
Debug.Assert(DirectorySeparatorChar == VolumeSeparatorChar);
41+
return IsDirectorySeparator(c);
42+
}
43+
44+
private static void EmulateFileIOPermissionChecks(string fullPath)
45+
{
46+
CheckInvalidPathChars(fullPath, true);
47+
}
48+
49+
private static string NormalizePath(
50+
string path, bool fullCheck,
51+
int maxPathLength, bool expandShortPaths) // ignored on Unix
52+
{
53+
Debug.Assert(path != null);
54+
55+
// If we're doing a full path check, look for illegal path characters.
56+
if (fullCheck)
57+
{
58+
CheckInvalidPathChars(path);
59+
}
60+
61+
// TODO: Implement this
62+
throw new NotImplementedException();
63+
}
64+
65+
private static string RemoveLongPathPrefix(string path)
66+
{
67+
return path; // nop. There's nothing special about "long" paths on Unix.
68+
}
69+
70+
public static string GetTempPath()
71+
{
72+
// TODO: Implement this
73+
throw new NotImplementedException();
74+
}
75+
76+
private static string InternalGetTempFileName(bool checkHost)
77+
{
78+
// TODO: Implement this
79+
throw new NotImplementedException();
80+
}s
81+
82+
public static bool IsPathRooted(string path)
83+
{
84+
if (path == null)
85+
return false;
86+
87+
CheckInvalidPathChars(path);
88+
return path.Length > 0 && path[0] == DirectorySeparatorChar;
89+
}
90+
91+
private static int GetRootLength(string path)
92+
{
93+
CheckInvalidPathChars(path);
94+
return path.Length > 0 && IsDirectorySeparator(path[0]) ? 1 : 0;
95+
}
96+
97+
private static byte[] CreateCryptoRandomByteArray(int byteLength)
98+
{
99+
// TODO: Implement this
100+
throw new NotImplementedException();
101+
}
102+
}
103+
104+
}

0 commit comments

Comments
 (0)