From 032f173ea1913855514d447e574633d57cb148ba Mon Sep 17 00:00:00 2001
From: Edward Neal <55035479+edwardneal@users.noreply.github.com>
Date: Fri, 12 Dec 2025 21:08:11 +0000
Subject: [PATCH 1/6] Implement early infrastructure for OS-independent builds.
Also clean up the netfx-only s_isWindowsNT variable - this was originally
used to distinguish between Windows 9x and Windows NT!
---
.../src/Microsoft/Data/Common/AdapterUtil.cs | 76 +++++++++++++------
.../Data/Common/AdapterUtil.netfx.cs | 4 -
.../ConnectionPool/DbConnectionPoolGroup.cs | 7 --
3 files changed, 51 insertions(+), 36 deletions(-)
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs
index 08a6dcc2b8..b65f66ac72 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs
@@ -22,6 +22,7 @@
using Microsoft.Data.SqlClient;
using Microsoft.Identity.Client;
using Microsoft.SqlServer.Server;
+using Microsoft.Win32;
using IsolationLevel = System.Data.IsolationLevel;
#if NETFRAMEWORK
@@ -29,11 +30,6 @@
using System.Security.Permissions;
#endif
-#if _WINDOWS
-using System.Runtime.Versioning;
-using Microsoft.Win32;
-#endif
-
namespace Microsoft.Data.Common
{
///
@@ -68,6 +64,20 @@ internal static partial class ADP
///
internal const int MaxBufferAccessTokenExpiry = 600;
+ ///
+ /// This member returns true if the current OS platform is Windows.
+ ///
+ ///
+ /// This is a const on .NET Framework, and a property on .NET Core, because of differing API availability and JIT requirements.
+ /// .NET Framework will perform basic dead branch elimination when a const value is encountered, while .NET Core can trim Windows-specific code
+ /// when published to non-Windows platforms.
+ ///
+#if NETFRAMEWORK
+ public const bool IsWindows = true;
+#else
+ public static bool IsWindows => OperatingSystem.IsWindows();
+#endif
+
#region UDT
#if NETFRAMEWORK
private static readonly MethodInfo s_method = typeof(InvalidUdtException).GetMethod("Create", BindingFlags.NonPublic | BindingFlags.Static);
@@ -375,6 +385,26 @@ internal static AuthenticationException SSLCertificateAuthenticationException(st
internal static ArgumentOutOfRangeException NotSupportedEnumerationValue(Type type, string value, string method)
=> ArgumentOutOfRange(StringsHelper.GetString(Strings.ADP_NotSupportedEnumerationValue, type.Name, value, method), type.Name);
+ // Throws PlatformNotSupportedException if not running on Windows. Only included when compiling for .NET, since .NET Framework
+ // only runs on Windows.
+ [Conditional("NET")]
+ internal static void ThrowOnNonWindowsPlatform()
+ {
+ if (!IsWindows)
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+
+ [Conditional("NET")]
+ internal static void ThrowOnNonWindowsPlatform(string message)
+ {
+ if (!IsWindows)
+ {
+ throw new PlatformNotSupportedException(message);
+ }
+ }
+
internal static void CheckArgumentNull(object value, string parameterName)
{
if (value is null)
@@ -429,22 +459,19 @@ internal static ArgumentOutOfRangeException InvalidCommandBehavior(CommandBehavi
return InvalidEnumerationValue(typeof(CommandBehavior), (int)value);
}
-
- #if _UNIX
- internal static object LocalMachineRegistryValue(string subkey, string queryvalue)
- {
- // No registry in non-Windows environments
- return null;
- }
- #endif
- #if _WINDOWS
- [ResourceExposure(ResourceScope.Machine)]
- [ResourceConsumption(ResourceScope.Machine)]
internal static object LocalMachineRegistryValue(string subkey, string queryvalue)
{
- #if NETFRAMEWORK
+#if NET
+ if (!IsWindows)
+ {
+ // No registry in non-Windows environments
+ return null;
+ }
+#endif
+
+#if NETFRAMEWORK
new RegistryPermission(RegistryPermissionAccess.Read, $@"HKEY_LOCAL_MACHINE\{subkey}").Assert();
- #endif
+#endif
try
{
@@ -460,14 +487,13 @@ internal static object LocalMachineRegistryValue(string subkey, string queryvalu
ADP.TraceExceptionWithoutRethrow(e);
return null;
}
- #if NETFRAMEWORK
+#if NETFRAMEWORK
finally
{
CodeAccessPermission.RevertAssert();
}
- #endif
+#endif
}
- #endif
internal static void ValidateCommandBehavior(CommandBehavior value)
{
@@ -989,7 +1015,7 @@ private static string ConnectionStateMsg(ConnectionState state)
internal static ArgumentOutOfRangeException InvalidIsolationLevel(IsolationLevel value)
{
// @TODO: Use single line debug assert?
- #if DEBUG
+#if DEBUG
switch (value)
{
case IsolationLevel.Unspecified:
@@ -1002,7 +1028,7 @@ internal static ArgumentOutOfRangeException InvalidIsolationLevel(IsolationLevel
Debug.Fail("valid IsolationLevel " + value.ToString());
break;
}
- #endif
+#endif
return InvalidEnumerationValue(typeof(IsolationLevel), (int)value);
}
@@ -1334,7 +1360,7 @@ internal static ArgumentException InvalidOffsetValue(int value)
internal static ArgumentOutOfRangeException InvalidParameterDirection(ParameterDirection value)
{
// @TODO: Use single line debug assert?
- #if DEBUG
+#if DEBUG
switch (value)
{
case ParameterDirection.Input:
@@ -1344,7 +1370,7 @@ internal static ArgumentOutOfRangeException InvalidParameterDirection(ParameterD
Debug.Fail("valid ParameterDirection " + value.ToString());
break;
}
- #endif
+#endif
return InvalidEnumerationValue(typeof(ParameterDirection), (int)value);
}
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.netfx.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.netfx.cs
index c7427a6a8d..28faee5bb6 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.netfx.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.netfx.cs
@@ -31,10 +31,6 @@ internal static partial class ADP
///
internal const int MinimumTimeoutForTnirMs = 500;
- // @TODO: Use naming rules
- // @TODO: All values but Unix and Windows32NT are used today, for netfx this should always be Win32NT. We can likely hard code this to true for netfx.
- internal static readonly bool s_isWindowsNT = Environment.OSVersion.Platform == PlatformID.Win32NT;
-
#endregion
#region Utility Methods
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ConnectionPool/DbConnectionPoolGroup.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ConnectionPool/DbConnectionPoolGroup.cs
index 3a7b01945a..9b8247d381 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ConnectionPool/DbConnectionPoolGroup.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ConnectionPool/DbConnectionPoolGroup.cs
@@ -52,9 +52,6 @@ sealed internal class DbConnectionPoolGroup
internal DbConnectionPoolGroup(DbConnectionOptions connectionOptions, DbConnectionPoolKey key, DbConnectionPoolGroupOptions poolGroupOptions)
{
Debug.Assert(connectionOptions != null, "null connection options");
-#if NETFRAMEWORK
- Debug.Assert(poolGroupOptions == null || ADP.s_isWindowsNT, "should not have pooling options on Win9x");
-#endif
_connectionOptions = connectionOptions;
_poolKey = key;
@@ -142,10 +139,6 @@ internal IDbConnectionPool GetConnectionPool(SqlConnectionFactory connectionFact
IDbConnectionPool pool = null;
if (_poolGroupOptions != null)
{
-#if NETFRAMEWORK
- Debug.Assert(ADP.s_isWindowsNT, "should not be pooling on Win9x");
-#endif
-
DbConnectionPoolIdentity currentIdentity = DbConnectionPoolIdentity.NoIdentity;
if (_poolGroupOptions.PoolByIdentity)
From 20b8b983d8603df51cfa8cb78d76ce456b3062d9 Mon Sep 17 00:00:00 2001
From: Edward Neal <55035479+edwardneal@users.noreply.github.com>
Date: Fri, 12 Dec 2025 21:24:36 +0000
Subject: [PATCH 2/6] SqlFileStream
We only throw a PlatformNotSupportedException in the constructor; if this throws, there's no way execution can reach a property or method.
---
.../src/Microsoft.Data.SqlClient.csproj | 7 +-
.../netfx/src/Microsoft.Data.SqlClient.csproj | 4 +-
.../src/Interop/Windows/Kernel32/FileTypes.cs | 4 -
.../Windows/Kernel32/IoControlCodeAccess.cs | 4 -
.../Windows/Kernel32/IoControlTransferType.cs | 4 -
.../src/Interop/Windows/Kernel32/Kernel32.cs | 16 +---
.../Windows/NtDll/CreateDisposition.cs | 4 -
.../Interop/Windows/NtDll/CreateOptions.cs | 4 -
.../Interop/Windows/NtDll/DesiredAccess.cs | 4 -
.../Windows/NtDll/FileFullEaInformation.cs | 4 -
.../Windows/NtDll/ImpersonationLevel.cs | 4 -
.../Interop/Windows/NtDll/IoStatusBlock.cs | 4 -
.../src/Interop/Windows/NtDll/NtDll.cs | 4 -
.../Windows/NtDll/ObjectAttributeFlags.cs | 4 -
.../Interop/Windows/NtDll/ObjectAttributes.cs | 4 -
.../Windows/NtDll/SecurityQualityOfService.cs | 4 -
.../src/Interop/Windows/SystemErrors.cs | 4 -
.../src/Interop/Windows/UnicodeString.cs | 4 -
...FileStream.windows.cs => SqlFileStream.cs} | 6 +-
.../SqlTypes/SqlFileStream.netcore.unix.cs | 92 -------------------
20 files changed, 10 insertions(+), 175 deletions(-)
rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlTypes/{SqlFileStream.windows.cs => SqlFileStream.cs} (99%)
delete mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlTypes/SqlFileStream.netcore.unix.cs
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
index f8fc03f915..bd1a0661a5 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
@@ -1004,11 +1004,8 @@
Microsoft\Data\SqlDbTypeExtensions.cs
-
- Microsoft\Data\SqlTypes\SqlFileStream.netcore.unix.cs
-
-
- Microsoft\Data\SqlTypes\SqlFileStream.windows.cs
+
+ Microsoft\Data\SqlTypes\SqlFileStream.cs
Microsoft\Data\SqlTypes\SqlJson.cs
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
index e0974d0d44..94da06f86a 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
@@ -981,8 +981,8 @@
Microsoft\Data\SqlDbTypeExtensions.cs
-
- Microsoft\Data\SqlTypes\SqlFileStream.windows.cs
+
+ Microsoft\Data\SqlTypes\SqlFileStream.cs
Microsoft\Data\SqlTypes\SqlJson.cs
diff --git a/src/Microsoft.Data.SqlClient/src/Interop/Windows/Kernel32/FileTypes.cs b/src/Microsoft.Data.SqlClient/src/Interop/Windows/Kernel32/FileTypes.cs
index 8dbbd6fbde..59b1c67dcf 100644
--- a/src/Microsoft.Data.SqlClient/src/Interop/Windows/Kernel32/FileTypes.cs
+++ b/src/Microsoft.Data.SqlClient/src/Interop/Windows/Kernel32/FileTypes.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#if _WINDOWS
-
namespace Interop.Windows.Kernel32
{
internal class FileTypes
@@ -14,5 +12,3 @@ internal class FileTypes
internal const int FILE_TYPE_PIPE = 0x0003;
}
}
-
-#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Interop/Windows/Kernel32/IoControlCodeAccess.cs b/src/Microsoft.Data.SqlClient/src/Interop/Windows/Kernel32/IoControlCodeAccess.cs
index bbfce78672..a7f0c52f8a 100644
--- a/src/Microsoft.Data.SqlClient/src/Interop/Windows/Kernel32/IoControlCodeAccess.cs
+++ b/src/Microsoft.Data.SqlClient/src/Interop/Windows/Kernel32/IoControlCodeAccess.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#if _WINDOWS
-
using System;
namespace Interop.Windows.Kernel32
@@ -33,5 +31,3 @@ public enum IoControlCodeAccess
FILE_WRITE_DATA = 0x02
}
}
-
-#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Interop/Windows/Kernel32/IoControlTransferType.cs b/src/Microsoft.Data.SqlClient/src/Interop/Windows/Kernel32/IoControlTransferType.cs
index 8099827bc8..6b0e8571af 100644
--- a/src/Microsoft.Data.SqlClient/src/Interop/Windows/Kernel32/IoControlTransferType.cs
+++ b/src/Microsoft.Data.SqlClient/src/Interop/Windows/Kernel32/IoControlTransferType.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#if _WINDOWS
-
namespace Interop.Windows.Kernel32
{
///
@@ -37,5 +35,3 @@ public enum IoControlTransferType
METHOD_NEITHER
}
}
-
-#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Interop/Windows/Kernel32/Kernel32.cs b/src/Microsoft.Data.SqlClient/src/Interop/Windows/Kernel32/Kernel32.cs
index a938fa2fcc..3d06d03b1f 100644
--- a/src/Microsoft.Data.SqlClient/src/Interop/Windows/Kernel32/Kernel32.cs
+++ b/src/Microsoft.Data.SqlClient/src/Interop/Windows/Kernel32/Kernel32.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#if _WINDOWS
-
using System;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
@@ -11,7 +9,7 @@
using Microsoft.Data.Common;
using Microsoft.Win32.SafeHandles;
-#if !NETFRAMEWORK
+#if !NETFRAMEWORK && _WINDOWS
using Interop.Windows.Handles;
#endif
@@ -22,7 +20,7 @@ internal static class Kernel32
internal const ushort FILE_DEVICE_FILE_SYSTEM = 0x0009;
internal const uint SEM_FAILCRITICALERRORS = 1;
- #if !NETFRAMEWORK
+ #if _WINDOWS && !NETFRAMEWORK
internal const int LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
internal const int LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800;
#endif
@@ -57,7 +55,7 @@ internal static extern bool DeviceIoControl(
out uint cbBytesReturned,
IntPtr overlapped);
- #if NET
+ #if NET && _WINDOWS
[DllImport(DllName, ExactSpelling = true, SetLastError = true)]
public static extern bool FreeLibrary([In] IntPtr hModule);
#endif
@@ -75,17 +73,13 @@ internal static extern int GetFullPathName(
IntPtr lpFilePartOrNull);
#endif
- #if NET
+ #if NET && _WINDOWS
[DllImport(DllName, CharSet = CharSet.Ansi, BestFitMapping = false)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
- #endif
- #if NET
[DllImport(DllName, CharSet = CharSet.Ansi, BestFitMapping = false)]
public static extern IntPtr GetProcAddress(SafeLibraryHandle hModule, string lpProcName);
- #endif
- #if NET
[DllImport(DllName, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern SafeLibraryHandle LoadLibraryExW([In] string lpwLibFileName, [In] IntPtr hFile, [In] uint dwFlags);
#endif
@@ -94,5 +88,3 @@ internal static extern int GetFullPathName(
internal static extern bool SetThreadErrorMode(uint dwNewMode, out uint lpOldMode);
}
}
-
-#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/CreateDisposition.cs b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/CreateDisposition.cs
index 7502a94e64..8f03025bee 100644
--- a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/CreateDisposition.cs
+++ b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/CreateDisposition.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#if _WINDOWS
-
namespace Interop.Windows.NtDll
{
///
@@ -56,5 +54,3 @@ internal enum CreateDisposition : uint
FILE_OVERWRITE_IF = 5
}
}
-
-#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/CreateOptions.cs b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/CreateOptions.cs
index 5c169ec5a0..39677ab3d5 100644
--- a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/CreateOptions.cs
+++ b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/CreateOptions.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#if _WINDOWS
-
using System;
namespace Interop.Windows.NtDll
@@ -198,5 +196,3 @@ internal enum CreateOptions : uint
// FILE_OPEN_FOR_FREE_SPACE_QUERY = 0x00800000
}
}
-
-#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/DesiredAccess.cs b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/DesiredAccess.cs
index acf7f9ee0f..f15fbcf0dc 100644
--- a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/DesiredAccess.cs
+++ b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/DesiredAccess.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#if _WINDOWS
-
using System;
namespace Interop.Windows.NtDll
@@ -190,5 +188,3 @@ internal enum DesiredAccess : uint
FILE_GENERIC_EXECUTE = 0x20000000 // GENERIC_EXECUTE
}
}
-
-#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/FileFullEaInformation.cs b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/FileFullEaInformation.cs
index 5e545ce131..76322ce604 100644
--- a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/FileFullEaInformation.cs
+++ b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/FileFullEaInformation.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#if _WINDOWS
-
using System.Runtime.InteropServices;
namespace Interop.Windows.NtDll
@@ -37,5 +35,3 @@ internal struct FileFullEaInformation
}
}
-
-#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/ImpersonationLevel.cs b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/ImpersonationLevel.cs
index 70c606e95b..5386a4094b 100644
--- a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/ImpersonationLevel.cs
+++ b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/ImpersonationLevel.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#if _WINDOWS
-
namespace Interop.Windows.NtDll
{
///
@@ -41,5 +39,3 @@ internal enum ImpersonationLevel
SecurityDelegation = 3,
}
}
-
-#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/IoStatusBlock.cs b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/IoStatusBlock.cs
index 0e173186b8..7018ef3abd 100644
--- a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/IoStatusBlock.cs
+++ b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/IoStatusBlock.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#if _WINDOWS
-
using System;
using System.Runtime.InteropServices;
@@ -44,5 +42,3 @@ public struct IoStatus
}
}
}
-
-#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/NtDll.cs b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/NtDll.cs
index 20b5e314db..8dddda19d3 100644
--- a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/NtDll.cs
+++ b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/NtDll.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#if _WINDOWS
-
using System;
using System.IO;
using System.Runtime.InteropServices;
@@ -120,5 +118,3 @@ private static extern unsafe int NtCreateFile(
uint EaLength);
}
}
-
-#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/ObjectAttributeFlags.cs b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/ObjectAttributeFlags.cs
index 0f70ffa6cf..31dfd80ead 100644
--- a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/ObjectAttributeFlags.cs
+++ b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/ObjectAttributeFlags.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#if _WINDOWS
-
using System;
namespace Interop.Windows.NtDll
@@ -54,5 +52,3 @@ internal enum ObjectAttributeFlags : uint
// OBJ_VALID_ATTRIBUTES = 0x000001F2
}
}
-
-#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/ObjectAttributes.cs b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/ObjectAttributes.cs
index 3093763429..f3198f923e 100644
--- a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/ObjectAttributes.cs
+++ b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/ObjectAttributes.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#if _WINDOWS
-
using System;
namespace Interop.Windows.NtDll
@@ -60,5 +58,3 @@ public ObjectAttributes(
}
}
}
-
-#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/SecurityQualityOfService.cs b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/SecurityQualityOfService.cs
index 0cfa77a2d5..7f268255d9 100644
--- a/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/SecurityQualityOfService.cs
+++ b/src/Microsoft.Data.SqlClient/src/Interop/Windows/NtDll/SecurityQualityOfService.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#if _WINDOWS
-
using System.Runtime.InteropServices;
namespace Interop.Windows.NtDll
@@ -50,5 +48,3 @@ public SecurityQualityOfService(
public bool IsEffectiveOnly { get; set; }
}
}
-
-#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Interop/Windows/SystemErrors.cs b/src/Microsoft.Data.SqlClient/src/Interop/Windows/SystemErrors.cs
index 2265ee1427..40819ef4d9 100644
--- a/src/Microsoft.Data.SqlClient/src/Interop/Windows/SystemErrors.cs
+++ b/src/Microsoft.Data.SqlClient/src/Interop/Windows/SystemErrors.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#if _WINDOWS
-
namespace Interop.Windows
{
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382.aspx
@@ -22,5 +20,3 @@ internal class SystemErrors
internal const int ERROR_MR_MID_NOT_FOUND = 317;
}
}
-
-#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Interop/Windows/UnicodeString.cs b/src/Microsoft.Data.SqlClient/src/Interop/Windows/UnicodeString.cs
index 07ff56dbb4..7fc87decbf 100644
--- a/src/Microsoft.Data.SqlClient/src/Interop/Windows/UnicodeString.cs
+++ b/src/Microsoft.Data.SqlClient/src/Interop/Windows/UnicodeString.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#if _WINDOWS
-
using System.Runtime.InteropServices;
namespace Interop.Windows
@@ -36,5 +34,3 @@ public UnicodeString(char* buffer, int length)
}
}
}
-
-#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlTypes/SqlFileStream.windows.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlTypes/SqlFileStream.cs
similarity index 99%
rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlTypes/SqlFileStream.windows.cs
rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlTypes/SqlFileStream.cs
index 9338cf03b1..370794051a 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlTypes/SqlFileStream.windows.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlTypes/SqlFileStream.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#if _WINDOWS
-
using System;
using System.ComponentModel;
using System.Diagnostics;
@@ -104,6 +102,8 @@ public SqlFileStream(
FileOptions options,
long allocationSize)
{
+ ADP.ThrowOnNonWindowsPlatform(Strings.SqlFileStream_NotSupported);
+
// @TODO: Adopt netcore style format
#if NETFRAMEWORK
const string scopeFormat = " {0} access={1} options={2} path='{3}'";
@@ -963,5 +963,3 @@ private void ThrowIfDisposed()
#endregion
}
}
-
-#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlTypes/SqlFileStream.netcore.unix.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlTypes/SqlFileStream.netcore.unix.cs
deleted file mode 100644
index 3ba7e55237..0000000000
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlTypes/SqlFileStream.netcore.unix.cs
+++ /dev/null
@@ -1,92 +0,0 @@
-// 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.
-
-#if NET && _UNIX
-
-using System;
-using System.IO;
-
-namespace Microsoft.Data.SqlTypes
-{
- ///
- public sealed class SqlFileStream : Stream
- {
- ///
- public SqlFileStream(string path, byte[] transactionContext, FileAccess access)
- {
- throw new PlatformNotSupportedException(Strings.SqlFileStream_NotSupported);
- }
-
- ///
- public SqlFileStream(string path, byte[] transactionContext, FileAccess access, FileOptions options, Int64 allocationSize)
- {
- throw new PlatformNotSupportedException(Strings.SqlFileStream_NotSupported);
- }
-
- ///
- public string Name
- {
- get => throw new PlatformNotSupportedException(Strings.SqlFileStream_NotSupported);
- }
-
- ///
- public byte[] TransactionContext
- {
- get => throw new PlatformNotSupportedException(Strings.SqlFileStream_NotSupported);
- }
-
- ///
- public override bool CanRead
- {
- get => throw new PlatformNotSupportedException(Strings.SqlFileStream_NotSupported);
- }
-
- ///
- public override bool CanSeek
- {
- get => throw new PlatformNotSupportedException(Strings.SqlFileStream_NotSupported);
- }
-
- ///
- public override bool CanWrite
- {
- get => throw new PlatformNotSupportedException(Strings.SqlFileStream_NotSupported);
- }
-
- ///
- public override long Length
- {
- get => throw new PlatformNotSupportedException(Strings.SqlFileStream_NotSupported);
- }
-
- ///
- public override long Position
- {
- get => throw new PlatformNotSupportedException(Strings.SqlFileStream_NotSupported);
- set => throw new PlatformNotSupportedException(Strings.SqlFileStream_NotSupported);
- }
-
- ///
- public override void Flush() =>
- throw new PlatformNotSupportedException(Strings.SqlFileStream_NotSupported);
-
- ///
- public override int Read(byte[] buffer, int offset, int count) =>
- throw new PlatformNotSupportedException(Strings.SqlFileStream_NotSupported);
-
- ///
- public override long Seek(long offset, System.IO.SeekOrigin origin) =>
- throw new PlatformNotSupportedException(Strings.SqlFileStream_NotSupported);
-
- ///
- public override void SetLength(long value) =>
- throw new PlatformNotSupportedException(Strings.SqlFileStream_NotSupported);
-
- ///
- public override void Write(byte[] buffer, int offset, int count) =>
- throw new PlatformNotSupportedException(Strings.SqlFileStream_NotSupported);
- }
-}
-
-#endif
From 102ac3e95a4c1f57171a5c8404a8d4b914b392a0 Mon Sep 17 00:00:00 2001
From: Edward Neal <55035479+edwardneal@users.noreply.github.com>
Date: Fri, 12 Dec 2025 21:34:25 +0000
Subject: [PATCH 3/6] SqlColumnEncryptionCngProvider
---
.../src/Microsoft.Data.SqlClient.csproj | 7 +--
.../netfx/src/Microsoft.Data.SqlClient.csproj | 4 +-
...s.cs => SqlColumnEncryptionCngProvider.cs} | 11 ++--
...olumnEncryptionCngProvider.netcore.unix.cs | 56 -------------------
4 files changed, 11 insertions(+), 67 deletions(-)
rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/{SqlColumnEncryptionCngProvider.windows.cs => SqlColumnEncryptionCngProvider.cs} (97%)
delete mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCngProvider.netcore.unix.cs
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
index bd1a0661a5..e03e192cbd 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
@@ -722,11 +722,8 @@
Microsoft\Data\SqlClient\SqlColumnEncryptionCertificateStoreProvider.cs
-
- Microsoft\Data\SqlClient\SqlColumnEncryptionCngProvider.netcore.unix.cs
-
-
- Microsoft\Data\SqlClient\SqlColumnEncryptionCngProvider.windows.cs
+
+ Microsoft\Data\SqlClient\SqlColumnEncryptionCngProvider.cs
Microsoft\Data\SqlClient\SqlColumnEncryptionCspProvider.netcore.unix.cs
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
index 94da06f86a..e2847f931a 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
@@ -717,8 +717,8 @@
Microsoft\Data\SqlClient\SqlColumnEncryptionCertificateStoreProvider.cs
-
- Microsoft\Data\SqlClient\SqlColumnEncryptionCngProvider.windows.cs
+
+ Microsoft\Data\SqlClient\SqlColumnEncryptionCngProvider.cs
Microsoft\Data\SqlClient\SqlColumnEncryptionCspProvider.windows.cs
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCngProvider.windows.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCngProvider.cs
similarity index 97%
rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCngProvider.windows.cs
rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCngProvider.cs
index 802472f83e..8cdd1070cc 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCngProvider.windows.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCngProvider.cs
@@ -2,8 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#if _WINDOWS
-
+using Microsoft.Data.Common;
using Microsoft.Data.SqlClient.AlwaysEncrypted;
using System;
using System.Diagnostics.CodeAnalysis;
@@ -150,6 +149,8 @@ private static void GetCngProviderAndKeyId(string keyPath, bool isSystemOp, out
///
public override byte[] DecryptColumnEncryptionKey(string? masterKeyPath, string? encryptionAlgorithm, byte[]? encryptedColumnEncryptionKey)
{
+ ADP.ThrowOnNonWindowsPlatform();
+
// Validate the input parameters
ValidateNonEmptyKeyPath(masterKeyPath, isSystemOp: true);
@@ -176,6 +177,8 @@ public override byte[] DecryptColumnEncryptionKey(string? masterKeyPath, string?
///
public override byte[] EncryptColumnEncryptionKey(string? masterKeyPath, string? encryptionAlgorithm, byte[]? columnEncryptionKey)
{
+ ADP.ThrowOnNonWindowsPlatform();
+
// Validate the input parameters
ValidateNonEmptyKeyPath(masterKeyPath, isSystemOp: false);
@@ -202,15 +205,15 @@ public override byte[] EncryptColumnEncryptionKey(string? masterKeyPath, string?
///
public override byte[] SignColumnMasterKeyMetadata(string? masterKeyPath, bool allowEnclaveComputations)
{
+ ADP.ThrowOnNonWindowsPlatform();
throw new NotSupportedException();
}
///
public override bool VerifyColumnMasterKeyMetadata(string? masterKeyPath, bool allowEnclaveComputations, byte[]? signature)
{
+ ADP.ThrowOnNonWindowsPlatform();
throw new NotSupportedException();
}
}
}
-
-#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCngProvider.netcore.unix.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCngProvider.netcore.unix.cs
deleted file mode 100644
index 6ab8567e2a..0000000000
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCngProvider.netcore.unix.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-// 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.
-
-// @TODO: See if we can throw this when we would create this object
-#if NET && _UNIX
-
-using System;
-
-#nullable enable
-
-namespace Microsoft.Data.SqlClient
-{
- ///
- public class SqlColumnEncryptionCngProvider : SqlColumnEncryptionKeyStoreProvider
- {
- ///
- public const string ProviderName = @"MSSQL_CNG_STORE";
-
- ///
- /// This encryption keystore uses an asymmetric key as the column master key.
- ///
- internal const string MasterKeyType = @"asymmetric key";
-
- ///
- /// This encryption keystore uses the master key path to reference a CNG provider.
- ///
- internal const string KeyPathReference = @"Microsoft Cryptography API: Next Generation (CNG) provider";
-
- ///
- public override byte[] DecryptColumnEncryptionKey(string? masterKeyPath, string? encryptionAlgorithm, byte[]? encryptedColumnEncryptionKey)
- {
- throw new PlatformNotSupportedException();
- }
-
- ///
- public override byte[] EncryptColumnEncryptionKey(string? masterKeyPath, string? encryptionAlgorithm, byte[]? columnEncryptionKey)
- {
- throw new PlatformNotSupportedException();
- }
-
- ///
- public override byte[] SignColumnMasterKeyMetadata(string? masterKeyPath, bool allowEnclaveComputations)
- {
- throw new PlatformNotSupportedException();
- }
-
- ///
- public override bool VerifyColumnMasterKeyMetadata(string? masterKeyPath, bool allowEnclaveComputations, byte[]? signature)
- {
- throw new PlatformNotSupportedException();
- }
- }
-}
-
-#endif
From a2b5eebe1644fa15873501d0b2ad1128c299c0a9 Mon Sep 17 00:00:00 2001
From: Edward Neal <55035479+edwardneal@users.noreply.github.com>
Date: Fri, 12 Dec 2025 21:39:42 +0000
Subject: [PATCH 4/6] SqlColumnEncryptionCspProvider
---
.../src/Microsoft.Data.SqlClient.csproj | 7 +--
.../netfx/src/Microsoft.Data.SqlClient.csproj | 4 +-
...s.cs => SqlColumnEncryptionCspProvider.cs} | 11 ++--
...olumnEncryptionCspProvider.netcore.unix.cs | 56 -------------------
4 files changed, 11 insertions(+), 67 deletions(-)
rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/{SqlColumnEncryptionCspProvider.windows.cs => SqlColumnEncryptionCspProvider.cs} (98%)
delete mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCspProvider.netcore.unix.cs
diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
index e03e192cbd..9886e985a3 100644
--- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj
@@ -725,11 +725,8 @@
Microsoft\Data\SqlClient\SqlColumnEncryptionCngProvider.cs
-
- Microsoft\Data\SqlClient\SqlColumnEncryptionCspProvider.netcore.unix.cs
-
-
- Microsoft\Data\SqlClient\SqlColumnEncryptionCspProvider.windows.cs
+
+ Microsoft\Data\SqlClient\SqlColumnEncryptionCspProvider.cs
Microsoft\Data\SqlClient\SqlColumnEncryptionEnclaveProvider.cs
diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
index e2847f931a..efe1f3acee 100644
--- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj
@@ -720,8 +720,8 @@
Microsoft\Data\SqlClient\SqlColumnEncryptionCngProvider.cs
-
- Microsoft\Data\SqlClient\SqlColumnEncryptionCspProvider.windows.cs
+
+ Microsoft\Data\SqlClient\SqlColumnEncryptionCspProvider.cs
Microsoft\Data\SqlClient\SqlColumnEncryptionEnclaveProvider.cs
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCspProvider.windows.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCspProvider.cs
similarity index 98%
rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCspProvider.windows.cs
rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCspProvider.cs
index 33fe10fe66..cfeba977bd 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCspProvider.windows.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCspProvider.cs
@@ -2,8 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#if _WINDOWS
-
+using Microsoft.Data.Common;
using Microsoft.Data.SqlClient.AlwaysEncrypted;
using Microsoft.Win32;
using System;
@@ -152,6 +151,8 @@ private static int GetProviderType(string providerName, string keyPath, bool isS
///
public override byte[] DecryptColumnEncryptionKey(string? masterKeyPath, string? encryptionAlgorithm, byte[]? encryptedColumnEncryptionKey)
{
+ ADP.ThrowOnNonWindowsPlatform();
+
// Validate the input parameters
ValidateNonEmptyCSPKeyPath(masterKeyPath, isSystemOp: true);
@@ -178,6 +179,8 @@ public override byte[] DecryptColumnEncryptionKey(string? masterKeyPath, string?
///
public override byte[] EncryptColumnEncryptionKey(string? masterKeyPath, string? encryptionAlgorithm, byte[]? columnEncryptionKey)
{
+ ADP.ThrowOnNonWindowsPlatform();
+
// Validate the input parameters
ValidateNonEmptyCSPKeyPath(masterKeyPath, isSystemOp: false);
@@ -204,15 +207,15 @@ public override byte[] EncryptColumnEncryptionKey(string? masterKeyPath, string?
///
public override byte[] SignColumnMasterKeyMetadata(string? masterKeyPath, bool allowEnclaveComputations)
{
+ ADP.ThrowOnNonWindowsPlatform();
throw new NotSupportedException();
}
///
public override bool VerifyColumnMasterKeyMetadata(string? masterKeyPath, bool allowEnclaveComputations, byte[]? signature)
{
+ ADP.ThrowOnNonWindowsPlatform();
throw new NotSupportedException();
}
}
}
-
-#endif
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCspProvider.netcore.unix.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCspProvider.netcore.unix.cs
deleted file mode 100644
index f96841273c..0000000000
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCspProvider.netcore.unix.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-// 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.
-
-// @TODO: See if we can throw this when we would create this object
-#if NET && _UNIX
-
-using System;
-
-#nullable enable
-
-namespace Microsoft.Data.SqlClient
-{
- ///
- public class SqlColumnEncryptionCspProvider : SqlColumnEncryptionKeyStoreProvider
- {
- ///
- public const string ProviderName = @"MSSQL_CSP_PROVIDER";
-
- ///
- /// This encryption keystore uses an asymmetric key as the column master key.
- ///
- internal const string MasterKeyType = @"asymmetric key";
-
- ///
- /// This encryption keystore uses the master key path to reference a CSP provider.
- ///
- internal const string KeyPathReference = @"Microsoft Cryptographic Service Provider (CSP)";
-
- ///
- public override byte[] DecryptColumnEncryptionKey(string? masterKeyPath, string? encryptionAlgorithm, byte[]? encryptedColumnEncryptionKey)
- {
- throw new PlatformNotSupportedException();
- }
-
- ///
- public override byte[] EncryptColumnEncryptionKey(string? masterKeyPath, string? encryptionAlgorithm, byte[]? columnEncryptionKey)
- {
- throw new PlatformNotSupportedException();
- }
-
- ///
- public override byte[] SignColumnMasterKeyMetadata(string? masterKeyPath, bool allowEnclaveComputations)
- {
- throw new PlatformNotSupportedException();
- }
-
- ///
- public override bool VerifyColumnMasterKeyMetadata(string? masterKeyPath, bool allowEnclaveComputations, byte[]? signature)
- {
- throw new PlatformNotSupportedException();
- }
- }
-}
-
-#endif
From 37fa1e639345a05eb550093c82798c24e0fd5c8d Mon Sep 17 00:00:00 2001
From: Edward Neal <55035479+edwardneal@users.noreply.github.com>
Date: Fri, 12 Dec 2025 23:55:24 +0000
Subject: [PATCH 5/6] Manually inline ThrowOnNonWindowsPlatform
This is necessary because when an application using SqlClient is being published, the IL trimmer doesn't see that the throw helper throws an exception, and thus doesn't eliminate the code paths which call Windows-specific APIs. As a result, the Windows-specific API paths aren't removed from executables published for a Linux platform.
---
.../src/Microsoft/Data/Common/AdapterUtil.cs | 26 +++----------------
.../SqlColumnEncryptionCngProvider.cs | 20 +++++++++-----
.../SqlColumnEncryptionCspProvider.cs | 20 +++++++++-----
.../Microsoft/Data/SqlTypes/SqlFileStream.cs | 5 +++-
4 files changed, 36 insertions(+), 35 deletions(-)
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs
index b65f66ac72..714e1d0d15 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs
@@ -69,8 +69,10 @@ internal static partial class ADP
///
///
/// This is a const on .NET Framework, and a property on .NET Core, because of differing API availability and JIT requirements.
- /// .NET Framework will perform basic dead branch elimination when a const value is encountered, while .NET Core can trim Windows-specific code
- /// when published to non-Windows platforms.
+ /// .NET Framework will perform basic dead branch elimination when a const value is encountered, while .NET Core can trim Windows-specific
+ /// code when published to non-Windows platforms.
+ /// .NET Core's trimming is very limited though, so this must be used inline within methods to throw PlatformNotSupportedException,
+ /// rather than in a throw helper.
///
#if NETFRAMEWORK
public const bool IsWindows = true;
@@ -385,26 +387,6 @@ internal static AuthenticationException SSLCertificateAuthenticationException(st
internal static ArgumentOutOfRangeException NotSupportedEnumerationValue(Type type, string value, string method)
=> ArgumentOutOfRange(StringsHelper.GetString(Strings.ADP_NotSupportedEnumerationValue, type.Name, value, method), type.Name);
- // Throws PlatformNotSupportedException if not running on Windows. Only included when compiling for .NET, since .NET Framework
- // only runs on Windows.
- [Conditional("NET")]
- internal static void ThrowOnNonWindowsPlatform()
- {
- if (!IsWindows)
- {
- throw new PlatformNotSupportedException();
- }
- }
-
- [Conditional("NET")]
- internal static void ThrowOnNonWindowsPlatform(string message)
- {
- if (!IsWindows)
- {
- throw new PlatformNotSupportedException(message);
- }
- }
-
internal static void CheckArgumentNull(object value, string parameterName)
{
if (value is null)
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCngProvider.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCngProvider.cs
index 8cdd1070cc..fc65808cf1 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCngProvider.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCngProvider.cs
@@ -149,7 +149,10 @@ private static void GetCngProviderAndKeyId(string keyPath, bool isSystemOp, out
///
public override byte[] DecryptColumnEncryptionKey(string? masterKeyPath, string? encryptionAlgorithm, byte[]? encryptedColumnEncryptionKey)
{
- ADP.ThrowOnNonWindowsPlatform();
+ if (!ADP.IsWindows)
+ {
+ throw new PlatformNotSupportedException();
+ }
// Validate the input parameters
ValidateNonEmptyKeyPath(masterKeyPath, isSystemOp: true);
@@ -177,7 +180,10 @@ public override byte[] DecryptColumnEncryptionKey(string? masterKeyPath, string?
///
public override byte[] EncryptColumnEncryptionKey(string? masterKeyPath, string? encryptionAlgorithm, byte[]? columnEncryptionKey)
{
- ADP.ThrowOnNonWindowsPlatform();
+ if (!ADP.IsWindows)
+ {
+ throw new PlatformNotSupportedException();
+ }
// Validate the input parameters
ValidateNonEmptyKeyPath(masterKeyPath, isSystemOp: false);
@@ -205,15 +211,17 @@ public override byte[] EncryptColumnEncryptionKey(string? masterKeyPath, string?
///
public override byte[] SignColumnMasterKeyMetadata(string? masterKeyPath, bool allowEnclaveComputations)
{
- ADP.ThrowOnNonWindowsPlatform();
- throw new NotSupportedException();
+ throw ADP.IsWindows
+ ? new NotSupportedException()
+ : new PlatformNotSupportedException();
}
///
public override bool VerifyColumnMasterKeyMetadata(string? masterKeyPath, bool allowEnclaveComputations, byte[]? signature)
{
- ADP.ThrowOnNonWindowsPlatform();
- throw new NotSupportedException();
+ throw ADP.IsWindows
+ ? new NotSupportedException()
+ : new PlatformNotSupportedException();
}
}
}
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCspProvider.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCspProvider.cs
index cfeba977bd..73ee585dfa 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCspProvider.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCspProvider.cs
@@ -151,7 +151,10 @@ private static int GetProviderType(string providerName, string keyPath, bool isS
///
public override byte[] DecryptColumnEncryptionKey(string? masterKeyPath, string? encryptionAlgorithm, byte[]? encryptedColumnEncryptionKey)
{
- ADP.ThrowOnNonWindowsPlatform();
+ if (!ADP.IsWindows)
+ {
+ throw new PlatformNotSupportedException();
+ }
// Validate the input parameters
ValidateNonEmptyCSPKeyPath(masterKeyPath, isSystemOp: true);
@@ -179,7 +182,10 @@ public override byte[] DecryptColumnEncryptionKey(string? masterKeyPath, string?
///
public override byte[] EncryptColumnEncryptionKey(string? masterKeyPath, string? encryptionAlgorithm, byte[]? columnEncryptionKey)
{
- ADP.ThrowOnNonWindowsPlatform();
+ if (!ADP.IsWindows)
+ {
+ throw new PlatformNotSupportedException();
+ }
// Validate the input parameters
ValidateNonEmptyCSPKeyPath(masterKeyPath, isSystemOp: false);
@@ -207,15 +213,17 @@ public override byte[] EncryptColumnEncryptionKey(string? masterKeyPath, string?
///
public override byte[] SignColumnMasterKeyMetadata(string? masterKeyPath, bool allowEnclaveComputations)
{
- ADP.ThrowOnNonWindowsPlatform();
- throw new NotSupportedException();
+ throw ADP.IsWindows
+ ? new NotSupportedException()
+ : new PlatformNotSupportedException();
}
///
public override bool VerifyColumnMasterKeyMetadata(string? masterKeyPath, bool allowEnclaveComputations, byte[]? signature)
{
- ADP.ThrowOnNonWindowsPlatform();
- throw new NotSupportedException();
+ throw ADP.IsWindows
+ ? new NotSupportedException()
+ : new PlatformNotSupportedException();
}
}
}
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlTypes/SqlFileStream.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlTypes/SqlFileStream.cs
index 370794051a..0b46c28e75 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlTypes/SqlFileStream.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlTypes/SqlFileStream.cs
@@ -102,7 +102,10 @@ public SqlFileStream(
FileOptions options,
long allocationSize)
{
- ADP.ThrowOnNonWindowsPlatform(Strings.SqlFileStream_NotSupported);
+ if (!ADP.IsWindows)
+ {
+ throw new PlatformNotSupportedException(Strings.SqlFileStream_NotSupported);
+ }
// @TODO: Adopt netcore style format
#if NETFRAMEWORK
From a0636093c4f041dbdc5fca50ea22d0df5e554193 Mon Sep 17 00:00:00 2001
From: Edward Neal <55035479+edwardneal@users.noreply.github.com>
Date: Mon, 15 Dec 2025 17:36:45 +0000
Subject: [PATCH 6/6] Correct preprocessor directive indentation
---
.../src/Microsoft/Data/Common/AdapterUtil.cs | 26 +++++++++----------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs
index 714e1d0d15..e929836b00 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/AdapterUtil.cs
@@ -74,11 +74,11 @@ internal static partial class ADP
/// .NET Core's trimming is very limited though, so this must be used inline within methods to throw PlatformNotSupportedException,
/// rather than in a throw helper.
///
-#if NETFRAMEWORK
+ #if NETFRAMEWORK
public const bool IsWindows = true;
-#else
+ #else
public static bool IsWindows => OperatingSystem.IsWindows();
-#endif
+ #endif
#region UDT
#if NETFRAMEWORK
@@ -443,17 +443,17 @@ internal static ArgumentOutOfRangeException InvalidCommandBehavior(CommandBehavi
internal static object LocalMachineRegistryValue(string subkey, string queryvalue)
{
-#if NET
+ #if NET
if (!IsWindows)
{
// No registry in non-Windows environments
return null;
}
-#endif
+ #endif
-#if NETFRAMEWORK
+ #if NETFRAMEWORK
new RegistryPermission(RegistryPermissionAccess.Read, $@"HKEY_LOCAL_MACHINE\{subkey}").Assert();
-#endif
+ #endif
try
{
@@ -469,12 +469,12 @@ internal static object LocalMachineRegistryValue(string subkey, string queryvalu
ADP.TraceExceptionWithoutRethrow(e);
return null;
}
-#if NETFRAMEWORK
+ #if NETFRAMEWORK
finally
{
CodeAccessPermission.RevertAssert();
}
-#endif
+ #endif
}
internal static void ValidateCommandBehavior(CommandBehavior value)
@@ -997,7 +997,7 @@ private static string ConnectionStateMsg(ConnectionState state)
internal static ArgumentOutOfRangeException InvalidIsolationLevel(IsolationLevel value)
{
// @TODO: Use single line debug assert?
-#if DEBUG
+ #if DEBUG
switch (value)
{
case IsolationLevel.Unspecified:
@@ -1010,7 +1010,7 @@ internal static ArgumentOutOfRangeException InvalidIsolationLevel(IsolationLevel
Debug.Fail("valid IsolationLevel " + value.ToString());
break;
}
-#endif
+ #endif
return InvalidEnumerationValue(typeof(IsolationLevel), (int)value);
}
@@ -1342,7 +1342,7 @@ internal static ArgumentException InvalidOffsetValue(int value)
internal static ArgumentOutOfRangeException InvalidParameterDirection(ParameterDirection value)
{
// @TODO: Use single line debug assert?
-#if DEBUG
+ #if DEBUG
switch (value)
{
case ParameterDirection.Input:
@@ -1352,7 +1352,7 @@ internal static ArgumentOutOfRangeException InvalidParameterDirection(ParameterD
Debug.Fail("valid ParameterDirection " + value.ToString());
break;
}
-#endif
+ #endif
return InvalidEnumerationValue(typeof(ParameterDirection), (int)value);
}