2018-05-13 23:41:49 -04:00
using System ;
2019-06-25 19:21:08 -04:00
using System.Runtime.CompilerServices ;
2018-05-13 23:41:49 -04:00
using System.Runtime.InteropServices ;
2019-06-25 19:21:08 -04:00
using System.Security ;
2018-05-13 23:41:49 -04:00
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 ;
2018-10-26 14:24:07 -04:00
/// <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)]
2019-06-25 19:21:08 -04:00
public static extern bool AddIntegrityLabelToBoundaryDescriptor ( ref BoundaryDescriptorHandle BoundaryDescriptor , PSID IntegrityLabel ) ;
2018-10-26 14:24:07 -04:00
2018-05-13 23:41:49 -04:00
/// <summary>Adds a security identifier (SID) to the specified boundary descriptor.</summary>
2018-10-26 14:24:07 -04:00
/// <param name="BoundaryDescriptor">
/// A handle to the boundary descriptor. The <c>CreateBoundaryDescriptor</c> function returns this handle.
/// </param>
2018-05-13 23:41:49 -04:00
/// <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)]
2019-06-25 19:21:08 -04:00
public static extern bool AddSIDToBoundaryDescriptor ( ref BoundaryDescriptorHandle BoundaryDescriptor , PSID RequiredSid ) ;
2018-05-13 23:41:49 -04:00
/// <summary>Closes an open namespace handle.</summary>
2019-06-25 19:21:08 -04:00
/// <param name="Handle">The namespace handle. This handle is created by CreatePrivateNamespace or OpenPrivateNamespace.</param>
2018-05-13 23:41:49 -04:00
/// <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>
2019-06-25 19:21:08 -04:00
/// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
2018-05-13 23:41:49 -04:00
/// </returns>
2019-06-25 19:21:08 -04:00
/// <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 );
2018-05-13 23:41:49 -04:00
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
2019-06-25 19:21:08 -04:00
[PInvokeData("namespaceapi.h", MSDNShortId = "b9b74cf2-bf13-4ceb-9242-bc6a884ac6f1")]
2018-05-13 23:41:49 -04:00
[return: MarshalAs(UnmanagedType.U1)]
2018-10-26 14:24:07 -04:00
public static extern bool ClosePrivateNamespace ( NamespaceHandle Handle , uint Flags ) ;
2018-05-13 23:41:49 -04:00
/// <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")]
2018-10-26 14:24:07 -04:00
public static extern SafeBoundaryDescriptorHandle CreateBoundaryDescriptor ( string Name , [ Optional ] uint Flags ) ;
2018-05-13 23:41:49 -04:00
/// <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">
2018-10-26 14:24:07 -04:00
/// 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.
2018-05-13 23:41:49 -04:00
/// </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>
2018-10-26 14:24:07 -04:00
// 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
2018-05-13 23:41:49 -04:00
[DllImport(Lib.Kernel32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("WinBase.h", MSDNShortId = "ms682419")]
2019-06-25 19:21:08 -04:00
public static extern SafeNamespaceHandle CreatePrivateNamespace ( [ In , Optional ] SECURITY_ATTRIBUTES lpPrivateNamespaceAttributes , BoundaryDescriptorHandle lpBoundaryDescriptor , string lpAliasPrefix ) ;
2018-05-13 23:41:49 -04:00
/// <summary>Deletes the specified boundary descriptor.</summary>
2019-06-25 19:21:08 -04:00
/// <param name="BoundaryDescriptor">A handle to the boundary descriptor. The CreateBoundaryDescriptor function returns this handle.</param>
2018-05-13 23:41:49 -04:00
/// <returns>This function does not return a value.</returns>
2019-06-25 19:21:08 -04:00
/// <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 );
2018-05-13 23:41:49 -04:00
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
2019-06-25 19:21:08 -04:00
[SecurityCritical, SuppressUnmanagedCodeSecurity]
[PInvokeData("namespaceapi.h", MSDNShortId = "759d9cd9-9ef2-4bbe-9e99-8aec87f5ba4a")]
2018-10-26 14:24:07 -04:00
public static extern void DeleteBoundaryDescriptor ( BoundaryDescriptorHandle BoundaryDescriptor ) ;
2018-05-13 23:41:49 -04:00
/// <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>
2018-10-26 14:24:07 -04:00
/// <param name="lpAliasPrefix">
/// The prefix for the namespace. To create an object in this namespace, specify the object name as prefix\objectname.
/// </param>
2018-05-13 23:41:49 -04:00
/// <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")]
2019-06-25 19:21:08 -04:00
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 ) ;
2018-10-26 14:24:07 -04:00
/// <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)]
2019-06-25 19:21:08 -04:00
public struct NamespaceHandle : IHandle
2018-10-26 14:24:07 -04:00
{
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 ( ) ;
2019-06-25 19:21:08 -04:00
/// <inheritdoc/>
public IntPtr DangerousGetHandle ( ) = > handle ;
2018-10-26 14:24:07 -04:00
}
/// <summary>
/// Provides a <see cref="SafeHandle"/> to a boundary descriptor that releases a created BoundaryDescriptorHandle instance at
/// disposal using DeleteBoundaryDescriptor.
/// </summary>
2019-02-04 11:51:08 -05:00
public class SafeBoundaryDescriptorHandle : SafeHANDLE
2018-10-26 14:24:07 -04:00
{
/// <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 ;
2019-06-25 19:21:08 -04:00
/// <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 ) ;
}
2018-10-26 14:24:07 -04:00
/// <inheritdoc/>
2019-06-25 19:21:08 -04:00
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
protected override bool InternalReleaseHandle ( )
{
BoundaryDescriptorHandle h = handle ;
DeleteBoundaryDescriptor ( h ) ;
return true ;
}
2018-10-26 14:24:07 -04:00
}
2019-06-25 19:21:08 -04:00
/// <summary>Provides a <see cref="SafeHandle"/> to a that releases a created NamespaceHandle instance at disposal using ClosePrivateNamespace.</summary>
2019-02-04 11:51:08 -05:00
public class SafeNamespaceHandle : SafeHANDLE
2018-10-26 14:24:07 -04:00
{
2019-06-25 19:21:08 -04:00
internal uint flag = PRIVATE_NAMESPACE_FLAG_DESTROY ;
2018-10-26 14:24:07 -04:00
/// <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/>
2019-06-25 19:21:08 -04:00
protected override bool InternalReleaseHandle ( ) = > ClosePrivateNamespace ( handle , flag ) ;
2018-10-26 14:24:07 -04:00
}
2018-05-13 23:41:49 -04:00
}
}