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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions TH-NETII Windows API.sln
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "THNETII.WinApi.Headers.ApDe
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "THNETII.WinApi.Headers.AccCtrl", "src\THNETII.WinApi.Headers.AccCtrl\THNETII.WinApi.Headers.AccCtrl.csproj", "{8FA68C49-D060-4DE2-94A3-996320B314E2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "THNETII.WinApi.Headers.AclApi", "src\THNETII.WinApi.Headers.AclApi\THNETII.WinApi.Headers.AclApi.csproj", "{DAA939D2-0C4C-4136-A1C6-6073311E0F3F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -515,6 +517,18 @@ Global
{8FA68C49-D060-4DE2-94A3-996320B314E2}.Release|x64.Build.0 = Release|Any CPU
{8FA68C49-D060-4DE2-94A3-996320B314E2}.Release|x86.ActiveCfg = Release|Any CPU
{8FA68C49-D060-4DE2-94A3-996320B314E2}.Release|x86.Build.0 = Release|Any CPU
{DAA939D2-0C4C-4136-A1C6-6073311E0F3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DAA939D2-0C4C-4136-A1C6-6073311E0F3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DAA939D2-0C4C-4136-A1C6-6073311E0F3F}.Debug|x64.ActiveCfg = Debug|Any CPU
{DAA939D2-0C4C-4136-A1C6-6073311E0F3F}.Debug|x64.Build.0 = Debug|Any CPU
{DAA939D2-0C4C-4136-A1C6-6073311E0F3F}.Debug|x86.ActiveCfg = Debug|Any CPU
{DAA939D2-0C4C-4136-A1C6-6073311E0F3F}.Debug|x86.Build.0 = Debug|Any CPU
{DAA939D2-0C4C-4136-A1C6-6073311E0F3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DAA939D2-0C4C-4136-A1C6-6073311E0F3F}.Release|Any CPU.Build.0 = Release|Any CPU
{DAA939D2-0C4C-4136-A1C6-6073311E0F3F}.Release|x64.ActiveCfg = Release|Any CPU
{DAA939D2-0C4C-4136-A1C6-6073311E0F3F}.Release|x64.Build.0 = Release|Any CPU
{DAA939D2-0C4C-4136-A1C6-6073311E0F3F}.Release|x86.ActiveCfg = Release|Any CPU
{DAA939D2-0C4C-4136-A1C6-6073311E0F3F}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -555,6 +569,7 @@ Global
{E4A4DA91-3696-40A6-9834-E5FAACEF682E} = {9689DB3E-1ED7-478C-AC14-C734B0397619}
{C0B32983-2879-4DAD-B834-8A40570A35CA} = {9689DB3E-1ED7-478C-AC14-C734B0397619}
{8FA68C49-D060-4DE2-94A3-996320B314E2} = {9689DB3E-1ED7-478C-AC14-C734B0397619}
{DAA939D2-0C4C-4136-A1C6-6073311E0F3F} = {9689DB3E-1ED7-478C-AC14-C734B0397619}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6EF7C9CF-E403-4B60-AB44-5F9FFEB668B7}
Expand Down
8 changes: 4 additions & 4 deletions src-native-c/THNETII.WinApi.Sample.Native/main.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#include <AccCtrl.h>
#include <AclAPI.h>

int main(int argc, char* argv[])
{
ACE_HEADER instance;
FN_PROGRESS instance;
const int size = sizeof(instance);
const int value = ACE_OBJECT_TYPE_PRESENT;
const int value = NULL;

const void* ptr = AccFree;
const void* ptr = SetEntriesInAcl;

return EXIT_SUCCESS;
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
namespace THNETII.WinApi
namespace THNETII.WinApi
{
public static class NativeLibraryNames
{
public const string Advapi32 = "Advapi32.dll";
public const string KernelBase = "KernelBase.dll";
public const string Kernel32 = "Kernel32.dll";
public const string Ntdll = "Ntdll.dll";
Expand Down
2 changes: 1 addition & 1 deletion src/THNETII.WinApi.Headers.AccCtrl/EXPLICIT_ACCESS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public struct EXPLICIT_ACCESS_W
/// <seealso cref="BuildSecurityDescriptor"/>
/// <seealso cref="GetExplicitEntriesFromAcl"/>
/// <seealso cref="LookupSecurityDescriptorParts"/>
/// <seealso cref="SetEntriesInAcl"/>
/// <seealso cref="M:THNETII.WinApi.Native.AclApi.AclApiFunctions.SetEntriesInAcl(System.ReadOnlySpan{THNETII.WinApi.Native.AccCtrl.EXPLICIT_ACCESS},System.IntPtr,System.IntPtr@)"/>
/// <seealso cref="TRUSTEE"/>
#if !NETSTANDARD1_6
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
Expand Down
3 changes: 2 additions & 1 deletion src/THNETII.WinApi.Headers.AccCtrl/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
using System.Diagnostics.CodeAnalysis;

[assembly: SuppressMessage("Documentation", "CS1591: Missing XML comment for publicly visible type or member")]
[assembly: SuppressMessage("Documentation", "CA1200: Avoid using cref tags with a prefix")]
[assembly: SuppressMessage("Design", "CA1028: Enum Storage should be Int32")]
[assembly: SuppressMessage("Design", "CA1051: Do not declare visible instance fields")]
[assembly: SuppressMessage("Naming", "CA1714: Flags enums should have plural names")]
[assembly: SuppressMessage("Naming", "CA1707: Identifiers should not contain underscores")]
[assembly: SuppressMessage("Design", "CA1051: Do not declare visible instance fields")]
[assembly: SuppressMessage("Performance", "CA1815: Override equals and operator equals on value types")]
[assembly: SuppressMessage("Style", "IDE1006: Naming Styles")]
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="System.Security.AccessControl" Version="4.7.0">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="System.Security.AccessControl" Version="4.7.0" />
</ItemGroup>

<ItemGroup>
Expand Down
171 changes: 171 additions & 0 deletions src/THNETII.WinApi.Headers.AclApi/AclApiFunctions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
using System;
using System.Runtime.InteropServices;
using System.Security.AccessControl;

using THNETII.WinApi.Native.AccCtrl;
using THNETII.WinApi.Native.WinError;
using THNETII.WinApi.Native.WinNT;

#if NETSTANDARD1_6
using EntryPointNotFoundException = System.Exception;
#endif

namespace THNETII.WinApi.Native.AclApi
{
using static ACCESS_MODE;
using static NativeLibraryNames;
using static WinErrorConstants;

/// <summary>
/// Win32 Access Control APIs
/// </summary>
public static class AclApiFunctions
{
// C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\um\AclAPI.h, line 53
#region SetEntriesInAclA function
/// <inheritdoc cref="SetEntriesInAcl"/>
public static unsafe int SetEntriesInAclA(
ReadOnlySpan<EXPLICIT_ACCESS_A> pListOfExplicitEntries,
[Optional] IntPtr OldAcl,
out IntPtr NewAcl
)
{
fixed (EXPLICIT_ACCESS_A* ptrListOfExplicitEntries = pListOfExplicitEntries)
return SetEntriesInAclA(
pListOfExplicitEntries.Length,
ptrListOfExplicitEntries,
OldAcl,
out NewAcl);
}

[DllImport(Advapi32, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi)]
private static extern unsafe int SetEntriesInAclA(
[In] int cCountOfExplicitEntries,
[In] EXPLICIT_ACCESS_A* pListOfExplicitEntries,
[In, Optional] IntPtr OldAcl,
out IntPtr NewAcl
);
#endregion
// C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\um\AclAPI.h, line 62
#region SetEntriesInAclW function
/// <inheritdoc cref="SetEntriesInAcl"/>
public static unsafe int SetEntriesInAclW(
ReadOnlySpan<EXPLICIT_ACCESS_W> pListOfExplicitEntries,
[Optional] IntPtr OldAcl,
out IntPtr NewAcl
)
{
fixed (EXPLICIT_ACCESS_W* ptrListOfExplicitEntries = pListOfExplicitEntries)
return SetEntriesInAclW(
pListOfExplicitEntries.Length,
ptrListOfExplicitEntries,
OldAcl,
out NewAcl);
}

[DllImport(Advapi32, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode)]
private static extern unsafe int SetEntriesInAclW(
[In] int cCountOfExplicitEntries,
[In] EXPLICIT_ACCESS_W* pListOfExplicitEntries,
[In, Optional] IntPtr OldAcl,
out IntPtr NewAcl
);
// C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\um\AclAPI.h, line 53
#endregion
// C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\um\AclAPI.h, line 71
#region SetEntriesInAcl function
/// <summary>
/// The <see cref="SetEntriesInAcl"/> function creates a new <a href="https://docs.microsoft.com/windows/desktop/SecGloss/a-gly">access control list</a> (ACL) by merging new access control or audit control information into an existing <see cref="ACL"/> structure.
/// </summary>
/// <param name="pListOfExplicitEntries">A span of <see cref="EXPLICIT_ACCESS"/> structures that describe the access control information to merge into the existing ACL.</param>
/// <param name="OldAcl">A pointer to the existing ACL. This parameter can be <see cref="IntPtr.Zero"/>, in which case, the function creates a new ACL based on the <see cref="EXPLICIT_ACCESS"/> entries.</param>
/// <param name="NewAcl">A variable that receives a pointer to the new ACL. If the function succeeds, you must call the <see cref="LocalFree"/> function to free the returned buffer.</param>
/// <returns>
/// <para>If the function succeeds, the function returns <see cref="ERROR_SUCCESS"/>.</para>
/// <para>If the function fails, it returns a nonzero error code.</para>
/// </returns>
/// <remarks>
/// <para>Each entry in the array of <see cref="EXPLICIT_ACCESS"/> structures specifies access control or audit control information for a specified trustee. A trustee can be a user, group, or other <a href="https://docs.microsoft.com/windows/desktop/SecGloss/s-gly">security identifier</a> (SID) value, such as a <a href="https://docs.microsoft.com/windows/desktop/SecGloss/l-gly">logon identifier</a> or logon type (for instance, a Windows service or batch job). You can use a name or a SID to identify a trustee.</para>
/// <para>You can use the <see cref="SetEntriesInAcl"/> function to modify the list of <a href="https://docs.microsoft.com/windows/desktop/SecGloss/a-gly">access control entries</a> (ACEs) in a <a href="https://docs.microsoft.com/windows/desktop/SecGloss/d-gly">discretionary access control list</a> (DACL) or a <a href="https://docs.microsoft.com/windows/desktop/SecGloss/s-gly">system access control list</a> (SACL). Note that <see cref="SetEntriesInAcl"/> does not prevent you from mixing access control and audit control information in the same <see cref="ACL"/>; however, the resulting ACL will contain meaningless entries.</para>
/// <para>
/// For a DACL, the <see cref="EXPLICIT_ACCESS.grfAccessMode"/> member of the <see cref="EXPLICIT_ACCESS"/> structure specifies whether to allow, deny, or revoke access rights for the trustee. This member can specify one of the following values:
/// <list type="bullet">
/// <item><see cref="GRANT_ACCESS"/></item>
/// <item><see cref="SET_ACCESS"/></item>
/// <item><see cref="DENY_ACCESS"/></item>
/// <item><see cref="REVOKE_ACCESS"/></item>
/// </list>
/// For information about these values, see <see cref="ACCESS_MODE"/>.
/// </para>
/// <para>The <see cref="SetEntriesInAcl"/> function places any new access-denied ACEs at the beginning of the list of ACEs for the new <see cref="ACL"/>. This function places any new access-allowed ACEs just before any existing access-allowed ACEs.</para>
/// <para>
/// For a SACL, the <see cref="EXPLICIT_ACCESS.grfAccessMode"/> member of the <see cref="EXPLICIT_ACCESS"/> structure can specify the following values:
/// <list type="bullet">
/// <item><see cref="REVOKE_ACCESS"/></item>
/// <item><see cref="SET_AUDIT_FAILURE"/></item>
/// <item><see cref="SET_AUDIT_SUCCESS"/></item>
/// </list>
/// <see cref="SET_AUDIT_FAILURE"/> and <see cref="SET_AUDIT_SUCCESS"/> can be combined. For information about these values, see <see cref="ACCESS_MODE"/>.
/// </para>
/// <para>The <see cref="SetEntriesInAcl"/> function places any new system-audit ACEs at the beginning of the list of ACEs for the new ACL.</para>
/// <para>
/// <list type="table">
/// <listheader><term>Requirements</term></listheader>
/// <item><term><strong>Minimum supported client:</strong></term><description>Windows XP [desktop apps | UWP apps]</description></item>
/// <item><term><strong>Minimum supported server:</strong></term><description>Windows Server 2003 [desktop apps | UWP apps]</description></item>
/// </list>
/// </para>
/// <para>Microsoft Docs page: <a href="https://docs.microsoft.com/en-us/windows/win32/api/aclapi/nf-aclapi-setentriesinaclw">SetEntriesInAclW function</a></para>
/// </remarks>
/// <exception cref="DllNotFoundException">The native library containg the function could not be found.</exception>
/// <exception cref="EntryPointNotFoundException">Unable to find the entry point for the function in the native library.</exception>
/// <seealso cref="ACL"/>
/// <seealso cref="GenericAce"/>
/// <seealso cref="GenericAcl"/>
/// <seealso href="https://docs.microsoft.com/windows/desktop/SecAuthZ/access-control">Access Control</seealso>
/// <seealso href="https://docs.microsoft.com/windows/desktop/SecAuthZ/authorization-functions">Basic Access Control Functions</seealso>
/// <seealso cref="EXPLICIT_ACCESS"/>
/// <seealso cref="LocalFree"/>
public static unsafe int SetEntriesInAcl(
ReadOnlySpan<EXPLICIT_ACCESS> pListOfExplicitEntries,
[Optional] IntPtr OldAcl,
out IntPtr NewAcl
)
{
fixed (EXPLICIT_ACCESS* ptrListOfExplicitEntries = pListOfExplicitEntries)
return SetEntriesInAcl(
pListOfExplicitEntries.Length,
ptrListOfExplicitEntries,
OldAcl,
out NewAcl);
}

#if !NETSTANDARD1_6
[DllImport(Advapi32, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto)]
private static extern
#else
private static
#endif // !NETSTANDARD1_6
unsafe int SetEntriesInAcl(
[In] int cCountOfExplicitEntries,
[In] EXPLICIT_ACCESS* pListOfExplicitEntries,
[In, Optional] IntPtr OldAcl,
out IntPtr NewAcl
)
#if !NETSTANDARD1_6
;
#else
=> Marshal.SystemDefaultCharSize switch
{
1 => SetEntriesInAclA(cCountOfExplicitEntries,
(EXPLICIT_ACCESS_A*)pListOfExplicitEntries,
OldAcl, out NewAcl),
2 => SetEntriesInAclW(cCountOfExplicitEntries,
(EXPLICIT_ACCESS_W*)pListOfExplicitEntries,
OldAcl, out NewAcl),
_ => throw new PlatformNotSupportedException()
};
#endif // !NETSTANDARD1_6
#endregion
}
}
37 changes: 37 additions & 0 deletions src/THNETII.WinApi.Headers.AclApi/FN_PROGRESS.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Runtime.InteropServices;

using THNETII.WinApi.Native.AccCtrl;

namespace THNETII.WinApi.Native.AclApi
{
// C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\um\AclAPI.h, line 32
/// <summary>
/// <para>Progress Function</para>
/// <para>
/// Caller of tree operation implements this Progress function, then
/// passes its function pointer to tree operation.
/// Tree operation invokes Progress function to provide progress and error
/// information to the caller during the potentially long execution
/// of the tree operation. Tree operation provides the name of the object
/// last processed and the error status of the operation on that object.
/// Tree operation also passes the current InvokeSetting value.
/// Caller may change the InvokeSetting value, for example, from "Always"
/// to "Only On Error."
/// </para>
/// </summary>
/// <param name="pObjectName">name of object just processed</param>
/// <param name="Status">status of operation on object</param>
/// <param name="pInvokeSetting">Never, always,</param>
/// <param name="Args">Caller specific data</param>
/// <param name="SecuritySet">Whether security was set</param>
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate void FN_PROGRESS(
[In] LPWSTR pObjectName, // name of object just processed
[In] int Status, // status of operation on object
ref PROG_INVOKE_SETTING pInvokeSetting, // Never, always,
[In] IntPtr Args, // Caller specific data
[In, MarshalAs(UnmanagedType.Bool)]
bool SecuritySet // Whether security was set
);
}
13 changes: 13 additions & 0 deletions src/THNETII.WinApi.Headers.AclApi/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.

using System.Diagnostics.CodeAnalysis;

[assembly: SuppressMessage("Documentation", "CS0419: Ambiguous reference in cref attribute")]
[assembly: SuppressMessage("Naming", "CA1707: Identifiers should not contain underscores")]
[assembly: SuppressMessage("Design", "CA1051: Do not declare visible instance fields")]
[assembly: SuppressMessage("Performance", "CA1815: Override equals and operator equals on value types")]
[assembly: SuppressMessage("Style", "IDE1006: Naming Styles")]
[assembly: SuppressMessage("Usage", "PC003: Native API not available in UWP")]
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<LangVersion>8</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<TargetFrameworks>netstandard1.6;netstandard2.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<RootNamespace>THNETII.WinApi.Native.AclApi</RootNamespace>
<NoWarn>$(NoWarn);0419</NoWarn>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src-shared\THNETII.WinApi.NativeLibraryNames\THNETII.WinApi.NativeLibraryNames.csproj">
<PrivateAssets>All</PrivateAssets>
</ProjectReference>
<ProjectReference Include="..\THNETII.WinApi.Constants.WinError\THNETII.WinApi.Constants.WinError.csproj">
<PrivateAssets>All</PrivateAssets>
</ProjectReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\THNETII.WinApi.Headers.AccCtrl\THNETII.WinApi.Headers.AccCtrl.csproj" />
</ItemGroup>

</Project>