Vanara/PInvoke/Kernel32/NameSpaceApi.cs

327 lines
18 KiB
C#

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
namespace Vanara.PInvoke
{
public static partial class Kernel32
{
/// <summary>Indicates that the namespace is destroyed on closing.</summary>
public const uint PRIVATE_NAMESPACE_FLAG_DESTROY = 0x00000001;
/// <summary>
/// <para>Adds a new required security identifier (SID) to the specified boundary descriptor.</para>
/// </summary>
/// <param name="BoundaryDescriptor">
/// <para>A handle to the boundary descriptor. The CreateBoundaryDescriptor function returns this handle.</para>
/// </param>
/// <param name="IntegrityLabel">
/// <para>
/// A pointer to a SID structure that represents the mandatory integrity level for the namespace. Use one of the following RID values
/// to create the SID:
/// </para>
/// <para>
/// <c>SECURITY_MANDATORY_UNTRUSTED_RID</c><c>SECURITY_MANDATORY_LOW_RID</c><c>SECURITY_MANDATORY_MEDIUM_RID</c><c>SECURITY_MANDATORY_SYSTEM_RID</c><c>SECURITY_MANDATORY_PROTECTED_PROCESS_RID</c>
/// For more information, see Well-Known SIDs.
/// </para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>
/// A process can create a private namespace only with an integrity level that is equal to or lower than the current integrity level
/// of the process. Therefore, a high integrity-level process can create a high, medium or low integrity-level namespace. A medium
/// integrity-level process can create only a medium or low integrity-level namespace.
/// </para>
/// <para>
/// A process would usually specify a namespace at the same integrity level as the process for protection against squatting attacks
/// by lower integrity-level processes.
/// </para>
/// <para>
/// The security descriptor that the creator places on the namespace determines who can open the namespace. So a low or medium
/// integrity-level process could be given permission to open a high integrity level namespace if the security descriptor of the
/// namespace permits it.
/// </para>
/// <para>To compile an application that uses this function, define <c>_WIN32_WINNT</c> as 0x0601 or later.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-addintegritylabeltoboundarydescriptor BOOL
// AddIntegrityLabelToBoundaryDescriptor( HANDLE *BoundaryDescriptor, PSID IntegrityLabel );
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winbase.h", MSDNShortId = "6b56e664-7795-4e30-8bca-1e4df2764606")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AddIntegrityLabelToBoundaryDescriptor(ref BoundaryDescriptorHandle BoundaryDescriptor, PSID IntegrityLabel);
/// <summary>Adds a security identifier (SID) to the specified boundary descriptor.</summary>
/// <param name="BoundaryDescriptor">
/// A handle to the boundary descriptor. The <c>CreateBoundaryDescriptor</c> function returns this handle.
/// </param>
/// <param name="RequiredSid">A pointer to a <c>SID</c> structure.</param>
/// <returns>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call <c>GetLastError</c>.</para>
/// </returns>
// BOOL WINAPI AddSIDToBoundaryDescriptor( _Inout_ HANDLE *BoundaryDescriptor, _In_ PSID RequiredSid); https://msdn.microsoft.com/en-us/library/windows/desktop/ms681937(v=vs.85).aspx
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("WinBase.h", MSDNShortId = "ms681937")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AddSIDToBoundaryDescriptor(ref BoundaryDescriptorHandle BoundaryDescriptor, PSID RequiredSid);
/// <summary>Closes an open namespace handle.</summary>
/// <param name="Handle">The namespace handle. This handle is created by CreatePrivateNamespace or OpenPrivateNamespace.</param>
/// <param name="Flags">If this parameter is <c>PRIVATE_NAMESPACE_FLAG_DESTROY</c> (0x00000001), the namespace is destroyed.</param>
/// <returns>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>To compile an application that uses this function, define <c>_WIN32_WINNT</c> as 0x0600 or later.</remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/namespaceapi/nf-namespaceapi-closeprivatenamespace
// BOOLEAN ClosePrivateNamespace( HANDLE Handle, ULONG Flags );
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("namespaceapi.h", MSDNShortId = "b9b74cf2-bf13-4ceb-9242-bc6a884ac6f1")]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool ClosePrivateNamespace(NamespaceHandle Handle, uint Flags);
/// <summary>Creates a boundary descriptor.</summary>
/// <param name="Name">The name of the boundary descriptor.</param>
/// <param name="Flags">This parameter is reserved for future use.</param>
/// <returns>
/// <para>If the function succeeds, the return value is a handle to the boundary descriptor.</para>
/// <para>If the function fails, the return value is <c>NULL</c>. To get extended error information, call <c>GetLastError</c>.</para>
/// </returns>
// HANDLE WINAPI CreateBoundaryDescriptor( _In_ LPCTSTR Name, _In_ ULONG Flags); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682121(v=vs.85).aspx
[DllImport(Lib.Kernel32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("WinBase.h", MSDNShortId = "ms682121")]
public static extern SafeBoundaryDescriptorHandle CreateBoundaryDescriptor(string Name, [Optional] uint Flags);
/// <summary>Creates a private namespace.</summary>
/// <param name="lpPrivateNamespaceAttributes">
/// A pointer to a <c>SECURITY_ATTRIBUTES</c> structure that specifies the security attributes of the namespace object.
/// </param>
/// <param name="lpBoundaryDescriptor">
/// A descriptor that defines how the namespace is to be isolated. The caller must be within this boundary. The
/// <c>CreateBoundaryDescriptor</c> function creates a boundary descriptor.
/// </param>
/// <param name="lpAliasPrefix">
/// <para>The prefix for the namespace. To create an object in this namespace, specify the object name as prefix\objectname.</para>
/// <para>The system supports multiple private namespaces with the same name, as long as they define different boundaries.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns a handle to the new namespace.</para>
/// <para>If the function fails, the return value is <c>NULL</c>. To get extended error information, call <c>GetLastError</c>.</para>
/// </returns>
// HANDLE WINAPI CreatePrivateNamespace( _In_opt_ LPSECURITY_ATTRIBUTES lpPrivateNamespaceAttributes, _In_ LPVOID
// lpBoundaryDescriptor, _In_ LPCTSTR lpAliasPrefix); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682419(v=vs.85).aspx
[DllImport(Lib.Kernel32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("WinBase.h", MSDNShortId = "ms682419")]
public static extern SafeNamespaceHandle CreatePrivateNamespace([In, Optional] SECURITY_ATTRIBUTES lpPrivateNamespaceAttributes, BoundaryDescriptorHandle lpBoundaryDescriptor, string lpAliasPrefix);
/// <summary>Deletes the specified boundary descriptor.</summary>
/// <param name="BoundaryDescriptor">A handle to the boundary descriptor. The CreateBoundaryDescriptor function returns this handle.</param>
/// <returns>This function does not return a value.</returns>
/// <remarks>To compile an application that uses this function, define <c>_WIN32_WINNT</c> as 0x0600 or later.</remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/namespaceapi/nf-namespaceapi-deleteboundarydescriptor
// void DeleteBoundaryDescriptor( HANDLE BoundaryDescriptor );
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[SecurityCritical, SuppressUnmanagedCodeSecurity]
[PInvokeData("namespaceapi.h", MSDNShortId = "759d9cd9-9ef2-4bbe-9e99-8aec87f5ba4a")]
public static extern void DeleteBoundaryDescriptor(BoundaryDescriptorHandle BoundaryDescriptor);
/// <summary>Opens a private namespace.</summary>
/// <param name="lpBoundaryDescriptor">
/// A descriptor that defines how the namespace is to be isolated. The <c>CreateBoundaryDescriptor</c> function creates a boundary descriptor.
/// </param>
/// <param name="lpAliasPrefix">
/// The prefix for the namespace. To create an object in this namespace, specify the object name as prefix\objectname.
/// </param>
/// <returns>The function returns the handle to the existing namespace.</returns>
// HANDLE WINAPI OpenPrivateNamespace( _In_ LPVOID lpBoundaryDescriptor, _In_ LPCTSTR lpAliasPrefix); https://msdn.microsoft.com/en-us/library/windows/desktop/ms684318(v=vs.85).aspx
[PInvokeData("WinBase.h", MSDNShortId = "ms684318")]
public static SafeNamespaceHandle OpenPrivateNamespace(BoundaryDescriptorHandle lpBoundaryDescriptor, string lpAliasPrefix)
{
var h = OpenPrivateNamespaceInternal(lpBoundaryDescriptor, lpAliasPrefix);
h.flag = 0;
return h;
}
/// <summary>Opens a private namespace.</summary>
/// <param name="lpBoundaryDescriptor">
/// A descriptor that defines how the namespace is to be isolated. The <c>CreateBoundaryDescriptor</c> function creates a boundary descriptor.
/// </param>
/// <param name="lpAliasPrefix">
/// The prefix for the namespace. To create an object in this namespace, specify the object name as prefix\objectname.
/// </param>
/// <returns>The function returns the handle to the existing namespace.</returns>
[DllImport(Lib.Kernel32, SetLastError = false, CharSet = CharSet.Auto, EntryPoint = "OpenPrivateNamespace")]
[PInvokeData("WinBase.h", MSDNShortId = "ms684318")]
private static extern SafeNamespaceHandle OpenPrivateNamespaceInternal(BoundaryDescriptorHandle lpBoundaryDescriptor, string lpAliasPrefix);
/// <summary>Provides a handle to a boundary descriptor.</summary>
[StructLayout(LayoutKind.Sequential)]
public struct BoundaryDescriptorHandle : IHandle
{
private IntPtr handle;
/// <summary>Initializes a new instance of the <see cref="BoundaryDescriptorHandle"/> struct.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
public BoundaryDescriptorHandle(IntPtr preexistingHandle) => handle = preexistingHandle;
/// <summary>Returns an invalid handle by instantiating a <see cref="BoundaryDescriptorHandle"/> object with <see cref="IntPtr.Zero"/>.</summary>
public static BoundaryDescriptorHandle NULL => new BoundaryDescriptorHandle(IntPtr.Zero);
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
public bool IsNull => handle == IntPtr.Zero;
/// <summary>Performs an explicit conversion from <see cref="BoundaryDescriptorHandle"/> to <see cref="IntPtr"/>.</summary>
/// <param name="h">The handle.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator IntPtr(BoundaryDescriptorHandle h) => h.handle;
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="BoundaryDescriptorHandle"/>.</summary>
/// <param name="h">The pointer to a handle.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator BoundaryDescriptorHandle(IntPtr h) => new BoundaryDescriptorHandle(h);
/// <summary>Implements the operator !=.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(BoundaryDescriptorHandle h1, BoundaryDescriptorHandle h2) => !(h1 == h2);
/// <summary>Implements the operator ==.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(BoundaryDescriptorHandle h1, BoundaryDescriptorHandle h2) => h1.Equals(h2);
/// <inheritdoc/>
public override bool Equals(object obj) => obj is BoundaryDescriptorHandle h ? handle == h.handle : false;
/// <inheritdoc/>
public override int GetHashCode() => handle.GetHashCode();
/// <inheritdoc/>
public IntPtr DangerousGetHandle() => handle;
}
/// <summary>Provides a handle to a private namespace.</summary>
[StructLayout(LayoutKind.Sequential)]
public struct NamespaceHandle : IHandle
{
private IntPtr handle;
/// <summary>Initializes a new instance of the <see cref="NamespaceHandle"/> struct.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
public NamespaceHandle(IntPtr preexistingHandle) => handle = preexistingHandle;
/// <summary>Returns an invalid handle by instantiating a <see cref="NamespaceHandle"/> object with <see cref="IntPtr.Zero"/>.</summary>
public static NamespaceHandle NULL => new NamespaceHandle(IntPtr.Zero);
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
public bool IsNull => handle == IntPtr.Zero;
/// <summary>Performs an explicit conversion from <see cref="NamespaceHandle"/> to <see cref="IntPtr"/>.</summary>
/// <param name="h">The handle.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator IntPtr(NamespaceHandle h) => h.handle;
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="NamespaceHandle"/>.</summary>
/// <param name="h">The pointer to a handle.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator NamespaceHandle(IntPtr h) => new NamespaceHandle(h);
/// <summary>Implements the operator !=.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(NamespaceHandle h1, NamespaceHandle h2) => !(h1 == h2);
/// <summary>Implements the operator ==.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(NamespaceHandle h1, NamespaceHandle h2) => h1.Equals(h2);
/// <inheritdoc/>
public override bool Equals(object obj) => obj is NamespaceHandle h ? handle == h.handle : false;
/// <inheritdoc/>
public override int GetHashCode() => handle.GetHashCode();
/// <inheritdoc/>
public IntPtr DangerousGetHandle() => handle;
}
/// <summary>
/// Provides a <see cref="SafeHandle"/> to a boundary descriptor that releases a created BoundaryDescriptorHandle instance at
/// disposal using DeleteBoundaryDescriptor.
/// </summary>
public class SafeBoundaryDescriptorHandle : SafeHANDLE
{
/// <summary>Initializes a new instance of the <see cref="BoundaryDescriptorHandle"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeBoundaryDescriptorHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="BoundaryDescriptorHandle"/> class.</summary>
private SafeBoundaryDescriptorHandle() : base() { }
/// <summary>Performs an implicit conversion from <see cref="SafeBoundaryDescriptorHandle"/> to <see cref="BoundaryDescriptorHandle"/>.</summary>
/// <param name="h">The safe handle instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator BoundaryDescriptorHandle(SafeBoundaryDescriptorHandle h) => h.handle;
/// <summary>Adds a security identifier (SID) to the boundary descriptor.</summary>
/// <param name="pSid">A pointer to a <c>SID</c> structure.</param>
/// <returns>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call <c>GetLastError</c>.</para>
/// </returns>
public bool AddSid(PSID pSid)
{
BoundaryDescriptorHandle h = handle;
if (Marshal.ReadByte(pSid.DangerousGetHandle(), 7) == 16)
return AddIntegrityLabelToBoundaryDescriptor(ref h, pSid);
return AddSIDToBoundaryDescriptor(ref h, pSid);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
protected override bool InternalReleaseHandle()
{
BoundaryDescriptorHandle h = handle;
DeleteBoundaryDescriptor(h);
return true;
}
}
/// <summary>Provides a <see cref="SafeHandle"/> to a that releases a created NamespaceHandle instance at disposal using ClosePrivateNamespace.</summary>
public class SafeNamespaceHandle : SafeHANDLE
{
internal uint flag = PRIVATE_NAMESPACE_FLAG_DESTROY;
/// <summary>Initializes a new instance of the <see cref="NamespaceHandle"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeNamespaceHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
private SafeNamespaceHandle() : base()
{
}
/// <summary>Performs an implicit conversion from <see cref="SafeNamespaceHandle"/> to <see cref="NamespaceHandle"/>.</summary>
/// <param name="h">The safe handle instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator NamespaceHandle(SafeNamespaceHandle h) => h.handle;
/// <inheritdoc/>
protected override bool InternalReleaseHandle() => ClosePrivateNamespace(handle, flag);
}
}
}