mirror of https://github.com/dahall/Vanara.git
327 lines
18 KiB
C#
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);
|
|
}
|
|
}
|
|
} |