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); } } }