C# helper functions for privileges and elevated account status.
namespace TomsToolbox.Desktop
{
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;
using System.Windows.Interop;
using JetBrains.Annotations;
using TomsToolbox.Core;
/// <summary>
/// Helper Functions for Privileges and Elevation Status
/// </summary>
public static class UserAccountControl
{
private const int E_FAIL = -2147467259;
/// <summary>
/// Prompts the user for credential.
/// </summary>
/// <param name="parent">The parent for the dialog.</param>
/// <param name="caption">The caption.</param>
/// <param name="message">The message.</param>
/// <param name="authenticationError">The previous authentication error, if any; 0 to hide previous error information.</param>
/// <param name="template">The credential used to initialize the dialog; maybe <c>null</c> to start with an empty dialog.</param>
/// <returns>
/// The credentials entered by the user, or <c>null</c> if the user has canceled the operation.
/// </returns>
[CanBeNull]
public static NetworkCredential PromptForCredential([NotNull] IWin32Window parent, [CanBeNull] string caption, [CanBeNull] string message, int authenticationError, [CanBeNull] NetworkCredential template)
{
using (var inCredBuffer = PackAuthenticationBuffer(template))
{
return PromptForCredential(parent, caption, message, authenticationError, inCredBuffer);
}
}
/// <summary>
/// Logs on the user with the given credentials as an interactive user.
/// </summary>
/// <param name="credential">The credential.</param>
/// <param name="userToken">The user token.</param>
/// <returns>
/// 0 if the function succeeds, a HRESULT of the last error if the function fails.
/// </returns>
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "1#")]
public static int LogOnInteractiveUser([NotNull] this NetworkCredential credential, [CanBeNull] out SafeTokenHandle userToken)
{
return LogOnInteractiveUser(credential.UserName, credential.Domain, credential.Password, out userToken);
}
/// <summary>
/// Logs on the user with the given credentials as an interactive user.
/// </summary>
/// <param name="userName">Name of the user.</param>
/// <param name="domain">The domain.</param>
/// <param name="password">The password.</param>
/// <param name="userToken">The user token.</param>
/// <returns>
/// 0 if the function succeeds, a HRESULT of the last error if the function fails.
/// </returns>
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "3#")]
public static int LogOnInteractiveUser([CanBeNull] string userName, [CanBeNull] string domain, [CanBeNull] string password, [CanBeNull] out SafeTokenHandle userToken)
{
ParseUserDomain(ref userName, ref domain);
if (NativeMethods.LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out var pUserToken))
{
userToken = new SafeTokenHandle(pUserToken);
return 0;
}
userToken = null;
var error = Marshal.GetHRForLastWin32Error();
return error == 0 ? E_FAIL : error;
}
/// <summary>
/// The function checks whether the primary access token of the process belongs
/// to a user account that is a member of the local Administrators group, even if
/// it currently is not elevated.
/// </summary>
/// <returns>
/// Returns true if the primary access token of the process belongs to user
/// account that is a member of the local Administrators group. Returns false
/// if the token does not.
/// </returns>
/// <exception cref="System.ComponentModel.Win32Exception">
/// When any native Windows API call fails, the function throws a Win32Exception with the last error code.
/// </exception>
public static bool IsCurrentUserInAdminGroup()
{
// Open the access token of the current process for query and duplicate.
if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_QUERY | TOKEN_DUPLICATE, out var phToken))
{
throw new Win32Exception();
}
using (var hToken = new SafeTokenHandle(phToken))
{
return IsUserInAdminGroup(hToken);
}
}
/// <summary>
/// The function checks whether the object associated with the access token belongs
/// to a user account that is a member of the local Administrators group, even if
/// it currently is not elevated.
/// </summary>
/// <param name="userToken">The user token.</param>
/// <returns>
/// Returns true if the object associated with the access token belongs to user
/// account that is a member of the local Administrators group. Returns false
/// if the token does not.
/// </returns>
/// <exception cref="Win32Exception">
/// </exception>
/// <exception cref="System.ComponentModel.Win32Exception">When any native Windows API call fails, the function throws a Win32Exception with the last error code.</exception>
public static bool IsUserInAdminGroup([NotNull] SafeTokenHandle userToken)
{
// Determine whether system is running Windows Vista or later operating
// systems (major version >= 6) because they support linked tokens, but
// previous versions (major version < 6) do not.
var version = Environment.OSVersion.Version;
if ((version != null) && (version.Major >= 6))
{
// Running Windows Vista or later (major version >= 6).
// Determine token type: limited, elevated, or default.
// Allocate a buffer for the elevation type information.
using (var pElevationType = new SafeNativeMemory(sizeof(TOKEN_ELEVATION_TYPE)))
{
// Retrieve token elevation type information.
if (!NativeMethods.GetTokenInformation(userToken, TOKEN_INFORMATION_CLASS.TokenElevationType, pElevationType))
{
throw new Win32Exception();
}
// Marshal the TOKEN_ELEVATION_TYPE enum from native to .NET.
var elevType = pElevationType.ReadInt32().ToEnum<TOKEN_ELEVATION_TYPE>();
// If limited, get the linked elevated token for further check.
if (elevType == TOKEN_ELEVATION_TYPE.TokenElevationTypeLimited)
{
// Allocate a buffer for the linked token.
using (var pLinkedToken = new SafeNativeMemory(IntPtr.Size))
{
// Get the linked token.
if (!NativeMethods.GetTokenInformation(userToken, TOKEN_INFORMATION_CLASS.TokenLinkedToken, pLinkedToken))
{
throw new Win32Exception();
}
// Marshal the linked token value from native to .NET.
var hLinkedToken = pLinkedToken.ReadIntPtr();
using (var linkedToken = new SafeTokenHandle(hLinkedToken))
{
return IsAdministrator(linkedToken);
}
}
}
}
}
// CheckTokenMembership requires an impersonation token. If we just got
// a linked token, it already is an impersonation token. If we did not
// get a linked token, duplicate the original into an impersonation
// token for CheckTokenMembership.
if (!NativeMethods.DuplicateToken(userToken, SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, out var phTokenToCheck))
{
throw new Win32Exception();
}
using (var hTokenToCheck = new SafeTokenHandle(phTokenToCheck))
{
// Check if the token to be checked contains admin SID.
return IsAdministrator(hTokenToCheck);
}
}
/// <summary>
/// The function checks whether the current process is run as administrator.
/// In other words, it dictates whether the primary access token of the
/// process belongs to user account that is a member of the local
/// Administrators group and it is elevated.
/// </summary>
/// <returns>
/// Returns true if the primary access token of the process belongs to user
/// account that is a member of the local Administrators group and it is
/// elevated. Returns false if the token does not.
/// </returns>
public static bool IsRunAsAdmin()
{
using (var id = WindowsIdentity.GetCurrent())
{
var principal = new WindowsPrincipal(id);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
}
/// <summary>
/// Determines whether the current user is in the specified group.
/// </summary>
/// <param name="groupName">Name of the group.</param>
/// <returns>
/// <c>true</c> if the user blongs to the specified group; otherwise <c>false</c>
/// </returns>
public static bool IsCurrentUserInGroup([CanBeNull] string groupName)
{
using (var id = WindowsIdentity.GetCurrent())
{
var principal = new WindowsPrincipal(id);
return principal.IsInRole(groupName);
}
}
/// <summary>
/// Determines whether the current user is in the specified group.
/// </summary>
/// <param name="userToken">The user token.</param>
/// <param name="groupName">Name of the group.</param>
/// <returns>
/// <c>true</c> if the user blongs to the specified group; otherwise <c>false</c>
/// </returns>
[SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Runtime.InteropServices.SafeHandle.DangerousGetHandle")]
public static bool IsUserInGroup([NotNull] SafeTokenHandle userToken, [CanBeNull] string groupName)
{
var token = userToken.DangerousGetHandle();
if (token == IntPtr.Zero)
return false;
using (var id = new WindowsIdentity(token))
{
var principal = new WindowsPrincipal(id);
return principal.IsInRole(groupName);
}
}
/// <summary>
/// The function gets the elevation information of the current process. It
/// dictates whether the process is elevated or not. Token elevation is only
/// available on Windows Vista and newer operating systems, thus
/// IsProcessElevated throws a C++ exception if it is called on systems prior
/// to Windows Vista. It is not appropriate to use this function to determine
/// whether a process is run as administartor.
/// </summary>
/// <returns>
/// Returns true if the process is elevated. Returns false if it is not.
/// </returns>
/// <exception cref="System.ComponentModel.Win32Exception">
/// When any native Windows API call fails, the function throws a Win32Exception
/// with the last error code.
/// </exception>
/// <remarks>
/// TOKEN_INFORMATION_CLASS provides TokenElevationType to check the elevation
/// type (TokenElevationTypeDefault / TokenElevationTypeLimited /
/// TokenElevationTypeFull) of the process. It is different from TokenElevation
/// in that, when UAC is turned off, elevation type always returns
/// TokenElevationTypeDefault even though the process is elevated (Integrity
/// Level == High). In other words, it is not safe to say if the process is
/// elevated based on elevation type. Instead, we should use TokenElevation.
/// </remarks>
[SuppressMessage("Microsoft.Interoperability", "CA1404:CallGetLastErrorImmediatelyAfterPInvoke")]
public static bool IsProcessElevated()
{
// Open the access token of the current process with TOKEN_QUERY.
if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_QUERY, out var phToken))
{
throw new Win32Exception();
}
using (var hToken = new SafeTokenHandle(phToken))
{
// Allocate a buffer for the elevation information.
using (var pTokenElevation = new SafeNativeMemory<TOKEN_ELEVATION>())
{
// Retrieve token elevation information.
if (!NativeMethods.GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenElevation, pTokenElevation))
{
// When the process is run on operating systems prior to Windows
// Vista, GetTokenInformation returns false with the error code
// ERROR_INVALID_PARAMETER because TokenElevation is not supported
// on those operating systems.
if ((Marshal.GetLastWin32Error() & 0xFFFF) == ERROR_INVALID_PARAMETER)
{
// => so on XP we are always "Elevated"!
return true;
}
throw new Win32Exception();
}
// Marshal the TOKEN_ELEVATION struct from native to .NET object.
var elevation = (TOKEN_ELEVATION)pTokenElevation;
// TOKEN_ELEVATION.TokenIsElevated is a non-zero value if the token
// has elevated privileges; otherwise, a zero value.
return (elevation.TokenIsElevated != 0);
}
}
}
/// <summary>
/// The function gets the integrity level of the current process. Integrity
/// level is only available on Windows Vista and newer operating systems, thus
/// GetProcessIntegrityLevel throws a C++ exception if it is called on systems
/// prior to Windows Vista.
/// </summary>
/// <returns>
/// Returns the integrity level of the current process. It is usually one of
/// these values:
///
/// SECURITY_MANDATORY_UNTRUSTED_RID - means untrusted level. It is used
/// by processes started by the Anonymous group. Blocks most write access.
/// (SID: S-1-16-0x0)
///
/// SECURITY_MANDATORY_LOW_RID - means low integrity level. It is used by
/// Protected Mode Internet Explorer. Blocks write acess to most objects
/// (such as files and registry keys) on the system. (SID: S-1-16-0x1000)
///
/// SECURITY_MANDATORY_MEDIUM_RID - means medium integrity level. It is
/// used by normal applications being launched while UAC is enabled.
/// (SID: S-1-16-0x2000)
///
/// SECURITY_MANDATORY_HIGH_RID - means high integrity level. It is used
/// by administrative applications launched through elevation when UAC is
/// enabled, or normal applications if UAC is disabled and the user is an
/// administrator. (SID: S-1-16-0x3000)
///
/// SECURITY_MANDATORY_SYSTEM_RID - means system integrity level. It is
/// used by services and other system-level applications (such as Wininit,
/// Winlogon, Smss, etc.) (SID: S-1-16-0x4000)
/// </returns>
/// <exception cref="System.ComponentModel.Win32Exception">
/// When any native Windows API call fails, the function throws a Win32Exception
/// with the last error code.
/// </exception>
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
public static int GetProcessIntegrityLevel()
{
// Open the access token of the current process with TOKEN_QUERY.
if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_QUERY, out var phToken))
{
throw new Win32Exception();
}
using (var hToken = new SafeTokenHandle(phToken))
{
// Then we must query the size of the integrity level information
// associated with the token. Note that we expect GetTokenInformation
// to return false with the ERROR_INSUFFICIENT_BUFFER error code
// because we've given it a null buffer. On exit cbTokenIntegrityLevel will tell
// the size of the group information.
if (!NativeMethods.GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, IntPtr.Zero, 0, out var cbTokenIntegrityLevel))
{
var error = Marshal.GetLastWin32Error();
if (error != ERROR_INSUFFICIENT_BUFFER)
{
// When the process is run on operating systems prior to
// Windows Vista, GetTokenInformation returns false with the
// ERROR_INVALID_PARAMETER error code because
// TokenIntegrityLevel is not supported on those OS's.
throw new Win32Exception(error);
}
}
// Now we allocate a buffer for the integrity level information.
using (var pTokenIntegrityLevel = new SafeNativeMemory<TOKEN_MANDATORY_LABEL>(cbTokenIntegrityLevel))
{
// Now we ask for the integrity level information again. This may fail
// if an administrator has added this account to an additional group
// between our first call to GetTokenInformation and this one.
if (!NativeMethods.GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, pTokenIntegrityLevel))
{
throw new Win32Exception();
}
// Marshal the TOKEN_MANDATORY_LABEL struct from native to .NET object.
var tokenIntegrityLevel = (TOKEN_MANDATORY_LABEL)pTokenIntegrityLevel;
// Integrity Level SIDs are in the form of S-1-16-0xXXXX. (e.g.
// S-1-16-0x1000 stands for low integrity level SID). There is one
// and only one sub-authority.
var pIntegrityLevel = NativeMethods.GetSidSubAuthority(tokenIntegrityLevel.Label.Sid, 0);
return Marshal.ReadInt32(pIntegrityLevel);
}
}
}
/// <summary>
/// Gets a handle of the UAC (user account control) shield icon.
/// </summary>
/// <value>The handle of the icon.</value>
/// <returns>
/// The handle of the UAC (user account control) shield icon.
/// </returns>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Uac", Justification = "UAC is a common windows term.")]
public static IntPtr UacShieldIcon
{
get
{
var iconInfo = new SHSTOCKICONINFO();
iconInfo.cbSize = (uint)Marshal.SizeOf(iconInfo);
var hr = NativeMethods.SHGetStockIconInfo(
SHSTOCKICONID.SIID_SHIELD,
SHGSI.SHGSI_ICON | SHGSI.SHGSI_SMALLICON,
ref iconInfo);
return hr != 0 ? IntPtr.Zero : iconInfo.hIcon;
}
}
[NotNull]
[SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Runtime.InteropServices.SafeHandle.DangerousGetHandle")]
private static SafeNativeMemory PackAuthenticationBuffer([CanBeNull] NetworkCredential credential)
{
var userName = credential?.UserName;
if (string.IsNullOrEmpty(userName))
return new SafeNativeMemory();
var inCredSize = 0;
NativeMethods.CredPackAuthenticationBuffer(0, userName, string.Empty, IntPtr.Zero, ref inCredSize);
var buffer = new SafeNativeMemory(inCredSize);
NativeMethods.CredPackAuthenticationBuffer(0, userName, string.Empty, buffer.DangerousGetHandle(), ref inCredSize);
return buffer;
}
[CanBeNull]
[SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Runtime.InteropServices.SafeHandle.DangerousGetHandle")]
private static NetworkCredential PromptForCredential([NotNull] IWin32Window parent, [CanBeNull] string caption, [CanBeNull] string message, int authenticationError, [NotNull] SafeNativeMemory inCredBuffer)
{
var save = true;
uint authPackage = 0;
var credui = new CREDUI_INFO
{
cbSize = Marshal.SizeOf(typeof(CREDUI_INFO)),
pszCaptionText = caption,
pszMessageText = message,
hwndParent = parent.Handle
};
if (0 != NativeMethods.CredUIPromptForWindowsCredentials(ref credui, authenticationError, ref authPackage, inCredBuffer.DangerousGetHandle(), inCredBuffer.Size, out var outCredBufferPtr, out int outCredSize, ref save, 0))
return null;
using (var outCredBuffer = new SafeNativeMemory(outCredBufferPtr, outCredSize))
{
return UnpackAuthenticationBuffer(outCredBuffer);
}
}
[SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Runtime.InteropServices.SafeHandle.DangerousGetHandle")]
private static bool IsAdministrator([NotNull] SafeHandle hTokenToCheck)
{
var token = hTokenToCheck.DangerousGetHandle();
if (token == IntPtr.Zero)
return false;
using (var id = new WindowsIdentity(token))
{
var principal = new WindowsPrincipal(id);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
}
[CanBeNull]
[SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Runtime.InteropServices.SafeHandle.DangerousGetHandle")]
private static NetworkCredential UnpackAuthenticationBuffer([NotNull] SafeNativeMemory outCredBuffer)
{
const int maxLen = 100;
var usernameBuf = new StringBuilder(maxLen);
var passwordBuf = new StringBuilder(maxLen);
var domainBuf = new StringBuilder(maxLen);
var maxUserLen = maxLen;
var maxDomainLen = maxLen;
var maxPasswordLen = maxLen;
if (!NativeMethods.CredUnPackAuthenticationBuffer(1, outCredBuffer.DangerousGetHandle(), outCredBuffer.Size, usernameBuf, ref maxUserLen, domainBuf, ref maxDomainLen, passwordBuf, ref maxPasswordLen))
return null;
return new NetworkCredential()
{
UserName = usernameBuf.ToString(),
Password = passwordBuf.ToString(),
Domain = domainBuf.ToString()
};
}
private static void ParseUserDomain([CanBeNull] ref string userName, [CanBeNull] ref string domain)
{
if (string.IsNullOrEmpty(userName))
return;
if (!string.IsNullOrEmpty(domain))
return;
var parts = userName.Split('\\');
if (parts.Length != 2)
return;
domain = parts[0];
userName = parts[1];
}
// ReSharper disable MemberCanBePrivate.Local
// ReSharper disable UnusedMember.Local
private const int ERROR_INVALID_PARAMETER = 0x57;
// Token Specific Access Rights
private const uint TOKEN_DUPLICATE = 0x0002;
private const uint TOKEN_QUERY = 0x0008;
private const int ERROR_INSUFFICIENT_BUFFER = 122;
private const int LOGON32_PROVIDER_DEFAULT = 0;
private const int LOGON32_LOGON_INTERACTIVE = 2;
private enum TOKEN_INFORMATION_CLASS
{
TokenUser = 1,
TokenGroups,
TokenPrivileges,
TokenOwner,
TokenPrimaryGroup,
TokenDefaultDacl,
TokenSource,
TokenType,
TokenImpersonationLevel,
TokenStatistics,
TokenRestrictedSids,
TokenSessionId,
TokenGroupsAndPrivileges,
TokenSessionReference,
TokenSandBoxInert,
TokenAuditPolicy,
TokenOrigin,
TokenElevationType,
TokenLinkedToken,
TokenElevation,
TokenHasRestrictions,
TokenAccessInformation,
TokenVirtualizationAllowed,
TokenVirtualizationEnabled,
TokenIntegrityLevel,
TokenUIAccess,
TokenMandatoryPolicy,
TokenLogonSid,
MaxTokenInfoClass
}
private enum SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
}
private enum TOKEN_ELEVATION_TYPE
{
TokenElevationTypeDefault = 1,
TokenElevationTypeFull,
TokenElevationTypeLimited
}
[StructLayout(LayoutKind.Sequential)]
private struct SID_AND_ATTRIBUTES
{
public readonly IntPtr Sid;
public readonly uint Attributes;
}
[StructLayout(LayoutKind.Sequential)]
private struct TOKEN_ELEVATION
{
public readonly int TokenIsElevated;
}
[StructLayout(LayoutKind.Sequential)]
private struct TOKEN_MANDATORY_LABEL
{
public SID_AND_ATTRIBUTES Label;
}
[StructLayout(LayoutKind.Sequential)]
private struct CREDUI_INFO
{
public int cbSize;
public IntPtr hwndParent;
[MarshalAs(UnmanagedType.LPWStr), CanBeNull]
public string pszMessageText;
[MarshalAs(UnmanagedType.LPWStr), CanBeNull]
public string pszCaptionText;
public readonly IntPtr hbmBanner;
}
private enum SHSTOCKICONID : uint
{
SIID_SHIELD = 77
}
[Flags]
private enum SHGSI : uint
{
SHGSI_ICON = 0x000000100,
SHGSI_SMALLICON = 0x000000001
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct SHSTOCKICONINFO
{
public uint cbSize;
public readonly IntPtr hIcon;
public readonly int iSysIconIndex;
public readonly int iIcon;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
[CanBeNull]
public readonly string szPath;
}
private static class NativeMethods
{
[DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool OpenProcessToken(IntPtr hProcess, uint desiredAccess, out IntPtr hToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DuplicateToken([NotNull] SafeTokenHandle existingTokenHandle, SECURITY_IMPERSONATION_LEVEL impersonationLevel, out IntPtr duplicateTokenHandle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetTokenInformation([NotNull] SafeTokenHandle hToken, TOKEN_INFORMATION_CLASS tokenInfoClass, IntPtr pTokenInfo, int tokenInfoLength, out int returnLength);
[SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Runtime.InteropServices.SafeHandle.DangerousGetHandle")]
public static bool GetTokenInformation([NotNull] SafeTokenHandle hToken, TOKEN_INFORMATION_CLASS tokenInfoClass, [NotNull] SafeNativeMemory pTokenInfo)
{
return GetTokenInformation(hToken, tokenInfoClass, pTokenInfo.DangerousGetHandle(), pTokenInfo.Size, out _);
}
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetSidSubAuthority(IntPtr pSid, uint nSubAuthority);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool LogonUser([CanBeNull] string lpszUsername, [CanBeNull] string lpszDomain, [CanBeNull] string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);
[DllImport("credui.dll", CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.U4)]
public static extern uint CredUIPromptForWindowsCredentials(ref CREDUI_INFO info, int authError, ref uint authPackage, IntPtr inAuthBuffer,
int inAuthBufferSize, out IntPtr refOutAuthBuffer, out int refOutAuthBufferSize, [MarshalAs(UnmanagedType.Bool)] ref bool fSave, int flags);
[DllImport("credui.dll", CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CredUnPackAuthenticationBuffer(int dwFlags, IntPtr pAuthBuffer, int cbAuthBuffer, [CanBeNull] StringBuilder pszUserName, ref int pcchMaxUserName, [CanBeNull] StringBuilder pszDomainName, ref int pcchMaxDomainame, [CanBeNull] StringBuilder pszPassword, ref int pcchMaxPassword);
[DllImport("credui.dll", CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CredPackAuthenticationBuffer(int dwFlags, [CanBeNull] string pszUserName, [CanBeNull] string pszPassword, IntPtr pPackedCredentials, ref int pcbPackedCredentials);
[DllImport("Shell32.dll", SetLastError = false)]
public static extern int SHGetStockIconInfo(SHSTOCKICONID siid, SHGSI uFlags, ref SHSTOCKICONINFO psii);
}
}
}