From 9c1c0331da0163ce4b9da86634c65362270387f3 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 18 Mar 2026 03:36:38 +0000
Subject: [PATCH 1/8] Initial plan
From 51a9274b5bb580d93e085f30d58c725cb33c298a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 18 Mar 2026 03:59:01 +0000
Subject: [PATCH 2/8] Unify SECURITY_ATTRIBUTES code from
FileSystemAclExtensions and SafeFileHandle
Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com>
---
.../Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs | 8 ++++++++
.../src/System/IO/FileSystemAclExtensions.cs | 6 +-----
.../Win32/SafeHandles/SafeFileHandle.Windows.cs | 10 +---------
3 files changed, 10 insertions(+), 14 deletions(-)
diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs
index f390490f3a5848..ab67c7eb580831 100644
--- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs
+++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.IO;
using System.Runtime.InteropServices;
internal static partial class Interop
@@ -14,6 +15,13 @@ internal struct SECURITY_ATTRIBUTES
internal uint nLength;
internal unsafe void* lpSecurityDescriptor;
internal BOOL bInheritHandle;
+
+ internal static unsafe SECURITY_ATTRIBUTES Create(FileShare share) =>
+ new SECURITY_ATTRIBUTES
+ {
+ nLength = (uint)sizeof(SECURITY_ATTRIBUTES),
+ bInheritHandle = ((share & FileShare.Inheritable) != 0) ? BOOL.TRUE : BOOL.FALSE
+ };
}
}
}
diff --git a/src/libraries/System.IO.FileSystem.AccessControl/src/System/IO/FileSystemAclExtensions.cs b/src/libraries/System.IO.FileSystem.AccessControl/src/System/IO/FileSystemAclExtensions.cs
index 7c13c2efeb820b..0ced5282467074 100644
--- a/src/libraries/System.IO.FileSystem.AccessControl/src/System/IO/FileSystemAclExtensions.cs
+++ b/src/libraries/System.IO.FileSystem.AccessControl/src/System/IO/FileSystemAclExtensions.cs
@@ -269,11 +269,7 @@ private static unsafe SafeFileHandle CreateFileHandle(string fullPath, FileMode
SafeFileHandle handle;
- var secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES
- {
- nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES),
- bInheritHandle = ((share & FileShare.Inheritable) != 0) ? Interop.BOOL.TRUE : Interop.BOOL.FALSE,
- };
+ var secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create(share);
if (security != null)
{
diff --git a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs
index 3d5f8d22db02ba..088fb74dba577a 100644
--- a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs
+++ b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs
@@ -131,15 +131,7 @@ internal static SafeFileHandle Open(string fullPath, FileMode mode, FileAccess a
private static unsafe SafeFileHandle CreateFile(string fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options)
{
- Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default;
- if ((share & FileShare.Inheritable) != 0)
- {
- secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES
- {
- nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES),
- bInheritHandle = Interop.BOOL.TRUE
- };
- }
+ Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create(share);
int fAccess =
((access & FileAccess.Read) == FileAccess.Read ? Interop.Kernel32.GenericOperations.GENERIC_READ : 0) |
From a3650af1eb75821dd14d49ff1e6469f9c2c5a574 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 18 Mar 2026 05:07:37 +0000
Subject: [PATCH 3/8] Address review feedback: use Create(bool) factory, apply
to all SECURITY_ATTRIBUTES instances
Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com>
---
.../Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs | 11 ++++++++---
.../IO/FileSystem.DirectoryCreation.Windows.cs | 7 ++-----
.../src/Microsoft/Win32/RegistryKey.cs | 8 ++------
.../src/System/IO/FileSystemAclExtensions.cs | 2 +-
.../MemoryMappedFiles/MemoryMappedFile.Windows.cs | 13 ++-----------
.../src/System/IO/Pipes/PipeStream.Windows.cs | 12 ++----------
.../Win32/SafeHandles/SafeFileHandle.Windows.cs | 2 +-
.../src/System/Threading/EventWaitHandle.Windows.cs | 2 +-
.../src/System/Threading/Mutex.Windows.cs | 2 +-
.../src/System/Threading/Semaphore.Windows.cs | 2 +-
.../src/System/Threading/EventWaitHandleAcl.cs | 7 ++-----
.../src/System/Threading/MutexAcl.cs | 7 ++-----
.../src/System/Threading/SemaphoreAcl.cs | 7 ++-----
13 files changed, 27 insertions(+), 55 deletions(-)
diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs
index ab67c7eb580831..717db004ea319b 100644
--- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs
+++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.IO;
using System.Runtime.InteropServices;
internal static partial class Interop
@@ -16,11 +15,17 @@ internal struct SECURITY_ATTRIBUTES
internal unsafe void* lpSecurityDescriptor;
internal BOOL bInheritHandle;
- internal static unsafe SECURITY_ATTRIBUTES Create(FileShare share) =>
+ internal static unsafe SECURITY_ATTRIBUTES Create() =>
+ new SECURITY_ATTRIBUTES
+ {
+ nLength = (uint)sizeof(SECURITY_ATTRIBUTES)
+ };
+
+ internal static unsafe SECURITY_ATTRIBUTES Create(bool inheritable) =>
new SECURITY_ATTRIBUTES
{
nLength = (uint)sizeof(SECURITY_ATTRIBUTES),
- bInheritHandle = ((share & FileShare.Inheritable) != 0) ? BOOL.TRUE : BOOL.FALSE
+ bInheritHandle = inheritable ? BOOL.TRUE : BOOL.FALSE
};
}
}
diff --git a/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs b/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs
index dc26d7638964a9..3d09f196608d06 100644
--- a/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs
+++ b/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs
@@ -77,11 +77,8 @@ public static unsafe void CreateDirectory(string fullPath, byte[]? securityDescr
fixed (byte* pSecurityDescriptor = securityDescriptor)
{
- Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES
- {
- nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES),
- lpSecurityDescriptor = pSecurityDescriptor
- };
+ Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create();
+ secAttrs.lpSecurityDescriptor = pSecurityDescriptor;
while (stackDir.Count > 0)
{
diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs
index 0c622e950a8b1f..41155b164fbebd 100644
--- a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs
+++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs
@@ -215,18 +215,14 @@ public unsafe RegistryKey CreateSubKey(string subkey, RegistryKeyPermissionCheck
}
}
- Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default;
+ Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create();
byte[]? securityDescriptor = registrySecurity?.GetSecurityDescriptorBinaryForm();
fixed (void* pSecurityDescriptor = securityDescriptor)
{
if (pSecurityDescriptor is not null)
{
- secAttrs = new()
- {
- nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES),
- lpSecurityDescriptor = pSecurityDescriptor
- };
+ secAttrs.lpSecurityDescriptor = pSecurityDescriptor;
}
// By default, the new key will be writable.
diff --git a/src/libraries/System.IO.FileSystem.AccessControl/src/System/IO/FileSystemAclExtensions.cs b/src/libraries/System.IO.FileSystem.AccessControl/src/System/IO/FileSystemAclExtensions.cs
index 0ced5282467074..7fd33e7bf0bfa3 100644
--- a/src/libraries/System.IO.FileSystem.AccessControl/src/System/IO/FileSystemAclExtensions.cs
+++ b/src/libraries/System.IO.FileSystem.AccessControl/src/System/IO/FileSystemAclExtensions.cs
@@ -269,7 +269,7 @@ private static unsafe SafeFileHandle CreateFileHandle(string fullPath, FileMode
SafeFileHandle handle;
- var secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create(share);
+ Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create((share & FileShare.Inheritable) != 0);
if (security != null)
{
diff --git a/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs b/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs
index 2b1dc6e4651031..c35d4ea8394d72 100644
--- a/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs
+++ b/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs
@@ -254,16 +254,7 @@ private static SafeMemoryMappedFileHandle OpenCore(
/// Helper method used to extract the native binary security descriptor from the MemoryMappedFileSecurity
/// type. If pinningHandle is not null, caller must free it AFTER the call to CreateFile has returned.
///
- private static unsafe Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability)
- {
- Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default(Interop.Kernel32.SECURITY_ATTRIBUTES);
- if ((inheritability & HandleInheritability.Inheritable) != 0)
- {
- secAttrs = default;
- secAttrs.nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES);
- secAttrs.bInheritHandle = Interop.BOOL.TRUE;
- }
- return secAttrs;
- }
+ private static Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability) =>
+ Interop.Kernel32.SECURITY_ATTRIBUTES.Create((inheritability & HandleInheritability.Inheritable) != 0);
}
}
diff --git a/src/libraries/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Windows.cs b/src/libraries/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Windows.cs
index ddff733119a7a8..c7aaf4b8fba2eb 100644
--- a/src/libraries/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Windows.cs
+++ b/src/libraries/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Windows.cs
@@ -581,16 +581,8 @@ public virtual PipeTransmissionMode ReadMode
}
}
- internal static unsafe Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability)
- {
- Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES
- {
- nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES),
- bInheritHandle = ((inheritability & HandleInheritability.Inheritable) != 0) ? Interop.BOOL.TRUE : Interop.BOOL.FALSE
- };
-
- return secAttrs;
- }
+ internal static Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability) =>
+ Interop.Kernel32.SECURITY_ATTRIBUTES.Create((inheritability & HandleInheritability.Inheritable) != 0);
internal static unsafe Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability, PipeSecurity? pipeSecurity, ref GCHandle pinningHandle)
{
diff --git a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs
index 088fb74dba577a..ec41af86829f68 100644
--- a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs
+++ b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs
@@ -131,7 +131,7 @@ internal static SafeFileHandle Open(string fullPath, FileMode mode, FileAccess a
private static unsafe SafeFileHandle CreateFile(string fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options)
{
- Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create(share);
+ Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create((share & FileShare.Inheritable) != 0);
int fAccess =
((access & FileAccess.Read) == FileAccess.Read ? Interop.Kernel32.GenericOperations.GENERIC_READ : 0) |
diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs
index 56ca5a68836e33..a2d76c604a25d6 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs
@@ -58,7 +58,7 @@ private unsafe void CreateEventCore(
if (options.CurrentUserOnly)
{
securityDescriptorInfo = new(CurrentUserOnlyAceRights);
- securityAttributes.nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES);
+ securityAttributes = Interop.Kernel32.SECURITY_ATTRIBUTES.Create();
securityAttributes.lpSecurityDescriptor = (void*)securityDescriptorInfo.SecurityDescriptor;
securityAttributesPtr = &securityAttributes;
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs
index be9969806a49f8..74a9a3ef4bcb57 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs
@@ -48,7 +48,7 @@ private unsafe void CreateMutexCore(
if (options.CurrentUserOnly)
{
securityDescriptorInfo = new(CurrentUserOnlyAceRights);
- securityAttributes.nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES);
+ securityAttributes = Interop.Kernel32.SECURITY_ATTRIBUTES.Create();
securityAttributes.lpSecurityDescriptor = (void*)securityDescriptorInfo.SecurityDescriptor;
securityAttributesPtr = &securityAttributes;
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs
index a188850a54387d..ab597e1b08b3d1 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs
@@ -62,7 +62,7 @@ private unsafe void CreateSemaphoreCore(
if (options.CurrentUserOnly)
{
securityDescriptorInfo = new(CurrentUserOnlyAceRights);
- securityAttributes.nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES);
+ securityAttributes = Interop.Kernel32.SECURITY_ATTRIBUTES.Create();
securityAttributes.lpSecurityDescriptor = (void*)securityDescriptorInfo.SecurityDescriptor;
securityAttributesPtr = &securityAttributes;
}
diff --git a/src/libraries/System.Threading.AccessControl/src/System/Threading/EventWaitHandleAcl.cs b/src/libraries/System.Threading.AccessControl/src/System/Threading/EventWaitHandleAcl.cs
index 7db2afe4e8f804..4e43d709a51c81 100644
--- a/src/libraries/System.Threading.AccessControl/src/System/Threading/EventWaitHandleAcl.cs
+++ b/src/libraries/System.Threading.AccessControl/src/System/Threading/EventWaitHandleAcl.cs
@@ -46,11 +46,8 @@ public static unsafe EventWaitHandle Create(bool initialState, EventResetMode mo
fixed (byte* pSecurityDescriptor = eventSecurity.GetSecurityDescriptorBinaryForm())
{
- var secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES
- {
- nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES),
- lpSecurityDescriptor = pSecurityDescriptor
- };
+ Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create();
+ secAttrs.lpSecurityDescriptor = pSecurityDescriptor;
SafeWaitHandle handle = Interop.Kernel32.CreateEventEx(
(IntPtr)(&secAttrs),
diff --git a/src/libraries/System.Threading.AccessControl/src/System/Threading/MutexAcl.cs b/src/libraries/System.Threading.AccessControl/src/System/Threading/MutexAcl.cs
index 4185c032b1421a..13aaef9f46eb93 100644
--- a/src/libraries/System.Threading.AccessControl/src/System/Threading/MutexAcl.cs
+++ b/src/libraries/System.Threading.AccessControl/src/System/Threading/MutexAcl.cs
@@ -31,11 +31,8 @@ public static unsafe Mutex Create(bool initiallyOwned, string? name, out bool cr
fixed (byte* pSecurityDescriptor = mutexSecurity.GetSecurityDescriptorBinaryForm())
{
- var secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES
- {
- nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES),
- lpSecurityDescriptor = pSecurityDescriptor
- };
+ Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create();
+ secAttrs.lpSecurityDescriptor = pSecurityDescriptor;
SafeWaitHandle handle = Interop.Kernel32.CreateMutexEx(
(IntPtr)(&secAttrs),
diff --git a/src/libraries/System.Threading.AccessControl/src/System/Threading/SemaphoreAcl.cs b/src/libraries/System.Threading.AccessControl/src/System/Threading/SemaphoreAcl.cs
index 1235e6594a72d1..db7c400474dc65 100644
--- a/src/libraries/System.Threading.AccessControl/src/System/Threading/SemaphoreAcl.cs
+++ b/src/libraries/System.Threading.AccessControl/src/System/Threading/SemaphoreAcl.cs
@@ -48,11 +48,8 @@ public static unsafe Semaphore Create(int initialCount, int maximumCount, string
fixed (byte* pSecurityDescriptor = semaphoreSecurity.GetSecurityDescriptorBinaryForm())
{
- var secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES
- {
- nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES),
- lpSecurityDescriptor = pSecurityDescriptor
- };
+ Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create();
+ secAttrs.lpSecurityDescriptor = pSecurityDescriptor;
SafeWaitHandle handle = Interop.Kernel32.CreateSemaphoreEx(
(IntPtr)(&secAttrs),
From 3062a3312a0f0ff35c830271b2524e9516b17a18 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 18 Mar 2026 06:10:24 +0000
Subject: [PATCH 4/8] Add Create(void* lpSecurityDescriptor) overload, fold
lpSecurityDescriptor into factory calls
Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com>
---
.../Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs | 8 +++++++-
.../src/System/IO/FileSystem.DirectoryCreation.Windows.cs | 3 +--
.../src/Microsoft/Win32/RegistryKey.cs | 8 +++-----
.../src/System/Threading/EventWaitHandle.Windows.cs | 3 +--
.../src/System/Threading/Mutex.Windows.cs | 3 +--
.../src/System/Threading/Semaphore.Windows.cs | 3 +--
.../src/System/Threading/EventWaitHandleAcl.cs | 3 +--
.../src/System/Threading/MutexAcl.cs | 3 +--
.../src/System/Threading/SemaphoreAcl.cs | 3 +--
9 files changed, 17 insertions(+), 20 deletions(-)
diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs
index 717db004ea319b..248657a6ac1dcc 100644
--- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs
+++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs
@@ -1,7 +1,6 @@
// 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
@@ -21,6 +20,13 @@ internal static unsafe SECURITY_ATTRIBUTES Create() =>
nLength = (uint)sizeof(SECURITY_ATTRIBUTES)
};
+ internal static unsafe SECURITY_ATTRIBUTES Create(void* lpSecurityDescriptor) =>
+ new SECURITY_ATTRIBUTES
+ {
+ nLength = (uint)sizeof(SECURITY_ATTRIBUTES),
+ lpSecurityDescriptor = lpSecurityDescriptor
+ };
+
internal static unsafe SECURITY_ATTRIBUTES Create(bool inheritable) =>
new SECURITY_ATTRIBUTES
{
diff --git a/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs b/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs
index 3d09f196608d06..2ca88deabf1414 100644
--- a/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs
+++ b/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs
@@ -77,8 +77,7 @@ public static unsafe void CreateDirectory(string fullPath, byte[]? securityDescr
fixed (byte* pSecurityDescriptor = securityDescriptor)
{
- Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create();
- secAttrs.lpSecurityDescriptor = pSecurityDescriptor;
+ Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create(pSecurityDescriptor);
while (stackDir.Count > 0)
{
diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs
index 41155b164fbebd..e7e777cf71e857 100644
--- a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs
+++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs
@@ -215,15 +215,13 @@ public unsafe RegistryKey CreateSubKey(string subkey, RegistryKeyPermissionCheck
}
}
- Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create();
byte[]? securityDescriptor = registrySecurity?.GetSecurityDescriptorBinaryForm();
fixed (void* pSecurityDescriptor = securityDescriptor)
{
- if (pSecurityDescriptor is not null)
- {
- secAttrs.lpSecurityDescriptor = pSecurityDescriptor;
- }
+ Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = pSecurityDescriptor is not null
+ ? Interop.Kernel32.SECURITY_ATTRIBUTES.Create(pSecurityDescriptor)
+ : Interop.Kernel32.SECURITY_ATTRIBUTES.Create();
// By default, the new key will be writable.
int ret = Interop.Advapi32.RegCreateKeyEx(_hkey,
diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs
index a2d76c604a25d6..8fafab5771293d 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs
@@ -58,8 +58,7 @@ private unsafe void CreateEventCore(
if (options.CurrentUserOnly)
{
securityDescriptorInfo = new(CurrentUserOnlyAceRights);
- securityAttributes = Interop.Kernel32.SECURITY_ATTRIBUTES.Create();
- securityAttributes.lpSecurityDescriptor = (void*)securityDescriptorInfo.SecurityDescriptor;
+ securityAttributes = Interop.Kernel32.SECURITY_ATTRIBUTES.Create((void*)securityDescriptorInfo.SecurityDescriptor);
securityAttributesPtr = &securityAttributes;
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs
index 74a9a3ef4bcb57..74064811ed5681 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs
@@ -48,8 +48,7 @@ private unsafe void CreateMutexCore(
if (options.CurrentUserOnly)
{
securityDescriptorInfo = new(CurrentUserOnlyAceRights);
- securityAttributes = Interop.Kernel32.SECURITY_ATTRIBUTES.Create();
- securityAttributes.lpSecurityDescriptor = (void*)securityDescriptorInfo.SecurityDescriptor;
+ securityAttributes = Interop.Kernel32.SECURITY_ATTRIBUTES.Create((void*)securityDescriptorInfo.SecurityDescriptor);
securityAttributesPtr = &securityAttributes;
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs
index ab597e1b08b3d1..fab00cfb2a5819 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs
@@ -62,8 +62,7 @@ private unsafe void CreateSemaphoreCore(
if (options.CurrentUserOnly)
{
securityDescriptorInfo = new(CurrentUserOnlyAceRights);
- securityAttributes = Interop.Kernel32.SECURITY_ATTRIBUTES.Create();
- securityAttributes.lpSecurityDescriptor = (void*)securityDescriptorInfo.SecurityDescriptor;
+ securityAttributes = Interop.Kernel32.SECURITY_ATTRIBUTES.Create((void*)securityDescriptorInfo.SecurityDescriptor);
securityAttributesPtr = &securityAttributes;
}
}
diff --git a/src/libraries/System.Threading.AccessControl/src/System/Threading/EventWaitHandleAcl.cs b/src/libraries/System.Threading.AccessControl/src/System/Threading/EventWaitHandleAcl.cs
index 4e43d709a51c81..bc8035e3d19c1c 100644
--- a/src/libraries/System.Threading.AccessControl/src/System/Threading/EventWaitHandleAcl.cs
+++ b/src/libraries/System.Threading.AccessControl/src/System/Threading/EventWaitHandleAcl.cs
@@ -46,8 +46,7 @@ public static unsafe EventWaitHandle Create(bool initialState, EventResetMode mo
fixed (byte* pSecurityDescriptor = eventSecurity.GetSecurityDescriptorBinaryForm())
{
- Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create();
- secAttrs.lpSecurityDescriptor = pSecurityDescriptor;
+ Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create(pSecurityDescriptor);
SafeWaitHandle handle = Interop.Kernel32.CreateEventEx(
(IntPtr)(&secAttrs),
diff --git a/src/libraries/System.Threading.AccessControl/src/System/Threading/MutexAcl.cs b/src/libraries/System.Threading.AccessControl/src/System/Threading/MutexAcl.cs
index 13aaef9f46eb93..976c6dd98220e3 100644
--- a/src/libraries/System.Threading.AccessControl/src/System/Threading/MutexAcl.cs
+++ b/src/libraries/System.Threading.AccessControl/src/System/Threading/MutexAcl.cs
@@ -31,8 +31,7 @@ public static unsafe Mutex Create(bool initiallyOwned, string? name, out bool cr
fixed (byte* pSecurityDescriptor = mutexSecurity.GetSecurityDescriptorBinaryForm())
{
- Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create();
- secAttrs.lpSecurityDescriptor = pSecurityDescriptor;
+ Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create(pSecurityDescriptor);
SafeWaitHandle handle = Interop.Kernel32.CreateMutexEx(
(IntPtr)(&secAttrs),
diff --git a/src/libraries/System.Threading.AccessControl/src/System/Threading/SemaphoreAcl.cs b/src/libraries/System.Threading.AccessControl/src/System/Threading/SemaphoreAcl.cs
index db7c400474dc65..07507eb6f7ae12 100644
--- a/src/libraries/System.Threading.AccessControl/src/System/Threading/SemaphoreAcl.cs
+++ b/src/libraries/System.Threading.AccessControl/src/System/Threading/SemaphoreAcl.cs
@@ -48,8 +48,7 @@ public static unsafe Semaphore Create(int initialCount, int maximumCount, string
fixed (byte* pSecurityDescriptor = semaphoreSecurity.GetSecurityDescriptorBinaryForm())
{
- Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create();
- secAttrs.lpSecurityDescriptor = pSecurityDescriptor;
+ Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create(pSecurityDescriptor);
SafeWaitHandle handle = Interop.Kernel32.CreateSemaphoreEx(
(IntPtr)(&secAttrs),
From c4e787ad06b44dc16ccb15bc9c92f7bf5b778a83 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 18 Mar 2026 07:08:36 +0000
Subject: [PATCH 5/8] Delete GetSecAttrs helper from
MemoryMappedFile.Windows.cs, inline Create calls directly
Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
---
.../MemoryMappedFiles/MemoryMappedFile.Windows.cs | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs b/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs
index c35d4ea8394d72..1210d8945ba8a4 100644
--- a/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs
+++ b/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs
@@ -36,9 +36,7 @@ private static SafeMemoryMappedFileHandle CreateCore(
{
Debug.Assert(fileHandle is null || fileSize >= 0);
- Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(inheritability);
-
- if (fileHandle != null)
+ Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create((inheritability & HandleInheritability.Inheritable) != 0);
{
VerifyMemoryMappedFileAccess(access, capacity, fileSize);
}
@@ -107,7 +105,7 @@ private static SafeMemoryMappedFileHandle CreateOrOpenCore(
Debug.Assert(access != MemoryMappedFileAccess.Write, "Callers requesting write access shouldn't try to create a mmf");
SafeMemoryMappedFileHandle? handle = null;
- Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(inheritability);
+ Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create((inheritability & HandleInheritability.Inheritable) != 0);
int waitRetries = 14; //((2^13)-1)*10ms == approximately 1.4mins
int waitSleep = 0;
@@ -249,12 +247,5 @@ private static SafeMemoryMappedFileHandle OpenCore(
}
return handle;
}
-
- ///
- /// Helper method used to extract the native binary security descriptor from the MemoryMappedFileSecurity
- /// type. If pinningHandle is not null, caller must free it AFTER the call to CreateFile has returned.
- ///
- private static Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability) =>
- Interop.Kernel32.SECURITY_ATTRIBUTES.Create((inheritability & HandleInheritability.Inheritable) != 0);
}
}
From b74209c136c35fdddc97949a474047151c7fd1ef Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 18 Mar 2026 07:16:21 +0000
Subject: [PATCH 6/8] Rename lpSecurityDescriptor param to securityDescriptor;
remove unnecessary null check in RegistryKey
Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
---
.../Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs | 4 ++--
.../src/Microsoft/Win32/RegistryKey.cs | 4 +---
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs
index 248657a6ac1dcc..d0740344597f79 100644
--- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs
+++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SECURITY_ATTRIBUTES.cs
@@ -20,11 +20,11 @@ internal static unsafe SECURITY_ATTRIBUTES Create() =>
nLength = (uint)sizeof(SECURITY_ATTRIBUTES)
};
- internal static unsafe SECURITY_ATTRIBUTES Create(void* lpSecurityDescriptor) =>
+ internal static unsafe SECURITY_ATTRIBUTES Create(void* securityDescriptor) =>
new SECURITY_ATTRIBUTES
{
nLength = (uint)sizeof(SECURITY_ATTRIBUTES),
- lpSecurityDescriptor = lpSecurityDescriptor
+ lpSecurityDescriptor = securityDescriptor
};
internal static unsafe SECURITY_ATTRIBUTES Create(bool inheritable) =>
diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs
index e7e777cf71e857..0aa1b22d5f316d 100644
--- a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs
+++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/RegistryKey.cs
@@ -219,9 +219,7 @@ public unsafe RegistryKey CreateSubKey(string subkey, RegistryKeyPermissionCheck
fixed (void* pSecurityDescriptor = securityDescriptor)
{
- Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = pSecurityDescriptor is not null
- ? Interop.Kernel32.SECURITY_ATTRIBUTES.Create(pSecurityDescriptor)
- : Interop.Kernel32.SECURITY_ATTRIBUTES.Create();
+ Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create(pSecurityDescriptor);
// By default, the new key will be writable.
int ret = Interop.Advapi32.RegCreateKeyEx(_hkey,
From 11f93bcb1fae4385046c90ae32af378c530ab40c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 18 Mar 2026 10:55:55 +0000
Subject: [PATCH 7/8] Fix IDE0059: remove unnecessary = default initialization
of securityAttributes
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
---
.../src/System/Threading/EventWaitHandle.Windows.cs | 2 +-
.../src/System/Threading/Mutex.Windows.cs | 2 +-
.../src/System/Threading/Semaphore.Windows.cs | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs
index 8fafab5771293d..8d4e75df747a07 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs
@@ -51,7 +51,7 @@ private unsafe void CreateEventCore(
SafeWaitHandle handle;
int errorCode;
Thread.CurrentUserSecurityDescriptorInfo securityDescriptorInfo = default;
- Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributes = default;
+ Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributes;
if (!string.IsNullOrEmpty(name) && options.WasSpecified)
{
name = options.GetNameWithSessionPrefix(name);
diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs
index 74064811ed5681..b3f0f1c9214757 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs
@@ -40,7 +40,7 @@ private unsafe void CreateMutexCore(
out bool createdNew)
{
Thread.CurrentUserSecurityDescriptorInfo securityDescriptorInfo = default;
- Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributes = default;
+ Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributes;
Interop.Kernel32.SECURITY_ATTRIBUTES* securityAttributesPtr = null;
if (!string.IsNullOrEmpty(name) && options.WasSpecified)
{
diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs
index fab00cfb2a5819..7d65881f367fce 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs
@@ -55,7 +55,7 @@ private unsafe void CreateSemaphoreCore(
SafeWaitHandle myHandle;
int errorCode;
Thread.CurrentUserSecurityDescriptorInfo securityDescriptorInfo = default;
- Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributes = default;
+ Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributes;
if (!string.IsNullOrEmpty(name) && options.WasSpecified)
{
name = options.GetNameWithSessionPrefix(name);
From 0a9677245cf1e48bf37e74eeabf1aab8b6fe0f6e Mon Sep 17 00:00:00 2001
From: Adam Sitnik
Date: Wed, 18 Mar 2026 12:05:19 +0100
Subject: [PATCH 8/8] Apply suggestions from code review
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---
.../src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs b/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs
index 1210d8945ba8a4..e63931483b5b88 100644
--- a/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs
+++ b/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs
@@ -37,6 +37,8 @@ private static SafeMemoryMappedFileHandle CreateCore(
Debug.Assert(fileHandle is null || fileSize >= 0);
Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = Interop.Kernel32.SECURITY_ATTRIBUTES.Create((inheritability & HandleInheritability.Inheritable) != 0);
+
+ if (fileHandle is not null)
{
VerifyMemoryMappedFileAccess(access, capacity, fileSize);
}