using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
namespace Vanara.PInvoke
{
public static partial class Kernel32
{
/// Indicates that the namespace is destroyed on closing.
public const uint PRIVATE_NAMESPACE_FLAG_DESTROY = 0x00000001;
///
/// Adds a new required security identifier (SID) to the specified boundary descriptor.
///
///
/// A handle to the boundary descriptor. The CreateBoundaryDescriptor function returns this handle.
///
///
///
/// 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:
///
///
/// SECURITY_MANDATORY_UNTRUSTED_RIDSECURITY_MANDATORY_LOW_RIDSECURITY_MANDATORY_MEDIUM_RIDSECURITY_MANDATORY_SYSTEM_RIDSECURITY_MANDATORY_PROTECTED_PROCESS_RID
/// For more information, see Well-Known SIDs.
///
///
///
/// If the function succeeds, the return value is nonzero.
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
///
///
///
/// 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.
///
///
/// 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.
///
///
/// 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.
///
/// To compile an application that uses this function, define _WIN32_WINNT as 0x0601 or later.
///
// 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);
/// Adds a security identifier (SID) to the specified boundary descriptor.
///
/// A handle to the boundary descriptor. The CreateBoundaryDescriptor function returns this handle.
///
/// A pointer to a SID structure.
///
/// If the function succeeds, the return value is nonzero.
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
///
// 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);
/// Closes an open namespace handle.
/// The namespace handle. This handle is created by CreatePrivateNamespace or OpenPrivateNamespace.
/// If this parameter is PRIVATE_NAMESPACE_FLAG_DESTROY (0x00000001), the namespace is destroyed.
///
/// If the function succeeds, the return value is nonzero.
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
///
/// To compile an application that uses this function, define _WIN32_WINNT as 0x0600 or later.
// 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);
/// Creates a boundary descriptor.
/// The name of the boundary descriptor.
/// This parameter is reserved for future use.
///
/// If the function succeeds, the return value is a handle to the boundary descriptor.
/// If the function fails, the return value is NULL. To get extended error information, call GetLastError.
///
// 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);
/// Creates a private namespace.
///
/// A pointer to a SECURITY_ATTRIBUTES structure that specifies the security attributes of the namespace object.
///
///
/// A descriptor that defines how the namespace is to be isolated. The caller must be within this boundary. The
/// CreateBoundaryDescriptor function creates a boundary descriptor.
///
///
/// The prefix for the namespace. To create an object in this namespace, specify the object name as prefix\objectname.
/// The system supports multiple private namespaces with the same name, as long as they define different boundaries.
///
///
/// If the function succeeds, it returns a handle to the new namespace.
/// If the function fails, the return value is NULL. To get extended error information, call GetLastError.
///
// 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);
/// Deletes the specified boundary descriptor.
/// A handle to the boundary descriptor. The CreateBoundaryDescriptor function returns this handle.
/// This function does not return a value.
/// To compile an application that uses this function, define _WIN32_WINNT as 0x0600 or later.
// 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);
/// Opens a private namespace.
///
/// A descriptor that defines how the namespace is to be isolated. The CreateBoundaryDescriptor function creates a boundary descriptor.
///
///
/// The prefix for the namespace. To create an object in this namespace, specify the object name as prefix\objectname.
///
/// The function returns the handle to the existing namespace.
// 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;
}
/// Opens a private namespace.
///
/// A descriptor that defines how the namespace is to be isolated. The CreateBoundaryDescriptor function creates a boundary descriptor.
///
///
/// The prefix for the namespace. To create an object in this namespace, specify the object name as prefix\objectname.
///
/// The function returns the handle to the existing namespace.
[DllImport(Lib.Kernel32, SetLastError = false, CharSet = CharSet.Auto, EntryPoint = "OpenPrivateNamespace")]
[PInvokeData("WinBase.h", MSDNShortId = "ms684318")]
private static extern SafeNamespaceHandle OpenPrivateNamespaceInternal(BoundaryDescriptorHandle lpBoundaryDescriptor, string lpAliasPrefix);
/// Provides a handle to a boundary descriptor.
[StructLayout(LayoutKind.Sequential)]
public struct BoundaryDescriptorHandle : IHandle
{
private IntPtr handle;
/// Initializes a new instance of the struct.
/// An object that represents the pre-existing handle to use.
public BoundaryDescriptorHandle(IntPtr preexistingHandle) => handle = preexistingHandle;
/// Returns an invalid handle by instantiating a object with .
public static BoundaryDescriptorHandle NULL => new BoundaryDescriptorHandle(IntPtr.Zero);
/// Gets a value indicating whether this instance is a null handle.
public bool IsNull => handle == IntPtr.Zero;
/// Performs an explicit conversion from to .
/// The handle.
/// The result of the conversion.
public static explicit operator IntPtr(BoundaryDescriptorHandle h) => h.handle;
/// Performs an implicit conversion from to .
/// The pointer to a handle.
/// The result of the conversion.
public static implicit operator BoundaryDescriptorHandle(IntPtr h) => new BoundaryDescriptorHandle(h);
/// Implements the operator !=.
/// The first handle.
/// The second handle.
/// The result of the operator.
public static bool operator !=(BoundaryDescriptorHandle h1, BoundaryDescriptorHandle h2) => !(h1 == h2);
/// Implements the operator ==.
/// The first handle.
/// The second handle.
/// The result of the operator.
public static bool operator ==(BoundaryDescriptorHandle h1, BoundaryDescriptorHandle h2) => h1.Equals(h2);
///
public override bool Equals(object obj) => obj is BoundaryDescriptorHandle h ? handle == h.handle : false;
///
public override int GetHashCode() => handle.GetHashCode();
///
public IntPtr DangerousGetHandle() => handle;
}
/// Provides a handle to a private namespace.
[StructLayout(LayoutKind.Sequential)]
public struct NamespaceHandle : IHandle
{
private IntPtr handle;
/// Initializes a new instance of the struct.
/// An object that represents the pre-existing handle to use.
public NamespaceHandle(IntPtr preexistingHandle) => handle = preexistingHandle;
/// Returns an invalid handle by instantiating a object with .
public static NamespaceHandle NULL => new NamespaceHandle(IntPtr.Zero);
/// Gets a value indicating whether this instance is a null handle.
public bool IsNull => handle == IntPtr.Zero;
/// Performs an explicit conversion from to .
/// The handle.
/// The result of the conversion.
public static explicit operator IntPtr(NamespaceHandle h) => h.handle;
/// Performs an implicit conversion from to .
/// The pointer to a handle.
/// The result of the conversion.
public static implicit operator NamespaceHandle(IntPtr h) => new NamespaceHandle(h);
/// Implements the operator !=.
/// The first handle.
/// The second handle.
/// The result of the operator.
public static bool operator !=(NamespaceHandle h1, NamespaceHandle h2) => !(h1 == h2);
/// Implements the operator ==.
/// The first handle.
/// The second handle.
/// The result of the operator.
public static bool operator ==(NamespaceHandle h1, NamespaceHandle h2) => h1.Equals(h2);
///
public override bool Equals(object obj) => obj is NamespaceHandle h ? handle == h.handle : false;
///
public override int GetHashCode() => handle.GetHashCode();
///
public IntPtr DangerousGetHandle() => handle;
}
///
/// Provides a to a boundary descriptor that releases a created BoundaryDescriptorHandle instance at
/// disposal using DeleteBoundaryDescriptor.
///
public class SafeBoundaryDescriptorHandle : SafeHANDLE
{
/// Initializes a new instance of the class and assigns an existing handle.
/// An object that represents the pre-existing handle to use.
///
/// to reliably release the handle during the finalization phase; otherwise, (not recommended).
///
public SafeBoundaryDescriptorHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// Initializes a new instance of the class.
private SafeBoundaryDescriptorHandle() : base() { }
/// Performs an implicit conversion from to .
/// The safe handle instance.
/// The result of the conversion.
public static implicit operator BoundaryDescriptorHandle(SafeBoundaryDescriptorHandle h) => h.handle;
/// Adds a security identifier (SID) to the boundary descriptor.
/// A pointer to a SID structure.
///
/// If the function succeeds, the return value is nonzero.
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
///
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);
}
///
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
protected override bool InternalReleaseHandle()
{
BoundaryDescriptorHandle h = handle;
DeleteBoundaryDescriptor(h);
return true;
}
}
/// Provides a to a that releases a created NamespaceHandle instance at disposal using ClosePrivateNamespace.
public class SafeNamespaceHandle : SafeHANDLE
{
internal uint flag = PRIVATE_NAMESPACE_FLAG_DESTROY;
/// Initializes a new instance of the class and assigns an existing handle.
/// An object that represents the pre-existing handle to use.
///
/// to reliably release the handle during the finalization phase; otherwise, (not recommended).
///
public SafeNamespaceHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
private SafeNamespaceHandle() : base()
{
}
/// Performs an implicit conversion from to .
/// The safe handle instance.
/// The result of the conversion.
public static implicit operator NamespaceHandle(SafeNamespaceHandle h) => h.handle;
///
protected override bool InternalReleaseHandle() => ClosePrivateNamespace(handle, flag);
}
}
}