using System;
using System.Security.Principal;
using System.Runtime.InteropServices;
public class Impersonate
{
#region 模擬使用者
private WindowsImpersonationContext impersonationContext;
private const int LOGON32_LOGON_INTERACTIVE = 2;
private const int LOGON32_PROVIDER_DEFAULT = 0;
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
private static extern int LogonUser(string lpszUserName, string lpszDomain, string lpszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool CloseHandle(IntPtr handle);
public bool ImpersonateUser(string userName, string password, string domain)
{
IntPtr token = IntPtr.Zero, tokenDuplicate = IntPtr.Zero;
if (RevertToSelf())
{
if (LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
WindowsIdentity wi = new WindowsIdentity(tokenDuplicate);
impersonationContext = wi.Impersonate();
if (impersonationContext != null)
{
CloseHandle(tokenDuplicate); CloseHandle(token);
return true;
}
}
}
}
if (tokenDuplicate != IntPtr.Zero) CloseHandle(tokenDuplicate);
if (token != IntPtr.Zero) CloseHandle(token);
return false;
}
public void UndoImpersonation() { impersonationContext.Undo(); }
#endregion
#region 關機
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct TokPriv1Luid { public int Count; public long Luid; public int Attr; }
[DllImport("kernel32.dll", ExactSpelling = true)] private static extern IntPtr GetCurrentThread();
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] private static extern bool OpenThreadToken(IntPtr h, int acc, bool openAsSelf, ref IntPtr phtok);
[DllImport("advapi32.dll", SetLastError = true)] private static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] private static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)] private static extern bool ExitWindowsEx(int flg, int rea);
[DllImport("advapi32.dll")] private static extern bool InitiateSystemShutdown(string machinename, string message, long timeout, bool forceAppsClosed, bool rebootAfterShutdown);
private const int SE_PRIVILEGE_ENABLED = 0x00000002;
private const int TOKEN_QUERY = 0x00000008;
private const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
private const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
private const int EWX_SHUTDOWN = 0x00000001;
private const int EWX_FORCE = 0x00000004;
public bool ShutDown()
{
TokPriv1Luid tp = new TokPriv1Luid();
IntPtr hproc = GetCurrentThread(); // 注意:用 Thread Token 而非 Process Token
IntPtr htok = IntPtr.Zero;
bool result = OpenThreadToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, true, ref htok);
tp.Count = 1; tp.Luid = 0; tp.Attr = SE_PRIVILEGE_ENABLED;
result = LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);
result = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
result = InitiateSystemShutdown("", "", 60, true, false); // 60 秒倒數、強制關閉應用、不重開機
return result;
}
#endregion
}
LogonUser → DuplicateToken → WindowsIdentity.Impersonate。OpenThreadToken) 而非進程權杖,啟用 SeShutdownPrivilege 特權。InitiateSystemShutdown 發起關機,可指定延遲秒數、強制關閉應用程式、是否重開機。此功能極度敏感,僅限受信任的管理工具在嚴格存取控制下使用,切勿暴露於公開網頁介面。