Нельзя добавлять дескрипторы вместе (new IntPtr(hProcess.ToInt64() + hToken.ToInt64());
), что не имеет смысла.
Вам нужен дескриптор процесса, чтобы получить дескриптор токена процесса, а затем передать дескриптор токена в CheckTokenMembership
.
Вам также нужно закрыть эти ручки с помощью CloseHandle
.
using System;
using System.Runtime.InteropServices;
...
public class WinApi
{
public const int TOKEN_DUPLICATE = 0x0002;
public const int TOKEN_QUERY = 0x00000008;
public const int SecurityImpersonation = 2;
public const int TokenImpersonation = 2;
[DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);
[DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DuplicateTokenEx(IntPtr hTok, UInt32 DesiredAccess, IntPtr SecAttPtr, int ImpLvl, int TokType, out IntPtr TokenHandle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(ProcessAccessFlags processAccess, bool bInheritHandle, int processId);
[DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CreateWellKnownSid(WELL_KNOWN_SID_TYPE WellKnownSidType, IntPtr DomainSid, IntPtr pSid, ref uint cbSid);
[DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CheckTokenMembership(IntPtr TokenHandle, IntPtr SidToCheck, out bool IsMember);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int GetCurrentProcessId();
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int CloseHandle(IntPtr h);
}
public enum ProcessAccessFlags : uint
{
QueryInformation = 0x00000400,
QueryLimitedInformation = 0x1000
}
public enum WELL_KNOWN_SID_TYPE
{
WinBuiltinAdministratorsSid = 26
}
private static bool IsAdminGroupMember(int processId)
{
IntPtr hPriToken = IntPtr.Zero, hImpToken = IntPtr.Zero;
var hProcess = WinApi.OpenProcess(ProcessAccessFlags.QueryLimitedInformation, false, processId);
if (hProcess == IntPtr.Zero) hProcess = WinApi.OpenProcess(ProcessAccessFlags.QueryInformation, false, processId); // < Vista
var haveToken = WinApi.OpenProcessToken(hProcess, WinApi.TOKEN_DUPLICATE, out hPriToken);
if (haveToken)
{
haveToken = WinApi.DuplicateTokenEx(hPriToken, WinApi.TOKEN_QUERY, IntPtr.Zero, WinApi.SecurityImpersonation, WinApi.TokenImpersonation, out hImpToken);
WinApi.CloseHandle(hPriToken);
}
if (hProcess != IntPtr.Zero) WinApi.CloseHandle(hProcess);
if (haveToken)
{
uint cbSid = 0;
bool isMember = false;
WinApi.CreateWellKnownSid(WELL_KNOWN_SID_TYPE.WinBuiltinAdministratorsSid, IntPtr.Zero, IntPtr.Zero, ref cbSid);
IntPtr pSid = Marshal.AllocCoTaskMem(Convert.ToInt32(cbSid));
var succeed = pSid != IntPtr.Zero && WinApi.CreateWellKnownSid(WELL_KNOWN_SID_TYPE.WinBuiltinAdministratorsSid, IntPtr.Zero, pSid, ref cbSid);
succeed = succeed && WinApi.CheckTokenMembership(hImpToken, pSid, out isMember);
Marshal.FreeCoTaskMem(pSid);
WinApi.CloseHandle(hImpToken);
return succeed && isMember;
}
return false;
}
[STAThread]static void Main(/*string[] args*/)
{
bool admin = IsAdminGroupMember(WinApi.GetCurrentProcessId());
Console.WriteLine(string.Format("IsAdminGroupMember={0}", admin));
}