/// <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> public static bool IsProcessElevated() { bool fIsElevated = false; SafeTokenHandle hToken = null; int cbTokenElevation = 0; IntPtr pTokenElevation = IntPtr.Zero; try { // Open the access token of the current process with TOKEN_QUERY. if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle, NativeMethods.TOKEN_QUERY, out hToken)) { throw new Win32Exception(); } // Allocate a buffer for the elevation information. cbTokenElevation = Marshal.SizeOf(typeof(TOKEN_ELEVATION)); pTokenElevation = Marshal.AllocHGlobal(cbTokenElevation); if (pTokenElevation == IntPtr.Zero) { throw new Win32Exception(); } // Retrieve token elevation information. if (!NativeMethods.GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenElevation, pTokenElevation, cbTokenElevation, out cbTokenElevation)) { // 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. throw new Win32Exception(); } // Marshal the TOKEN_ELEVATION struct from native to .NET object. TOKEN_ELEVATION elevation = (TOKEN_ELEVATION)Marshal.PtrToStructure( pTokenElevation, typeof(TOKEN_ELEVATION)); // TOKEN_ELEVATION.TokenIsElevated is a non-zero value if the token // has elevated privileges; otherwise, a zero value. fIsElevated = (elevation.TokenIsElevated != 0); } finally { // Centralized cleanup for all allocated resources. if (hToken != null) { hToken.Close(); hToken = null; } if (pTokenElevation != IntPtr.Zero) { Marshal.FreeHGlobal(pTokenElevation); pTokenElevation = IntPtr.Zero; cbTokenElevation = 0; } } return(fIsElevated); }
/// <summary> /// 此函数获取当前进程的权限提升信息。它由此进程是否进行了权限提升所 /// 决定。令牌权限提升只有在Windows Vista及后续版本的Windows中有效。所以在 /// Windows Vista之前的版本中执行IsProcessElevated, 它会抛出一个C++异常。 /// 此函数并不适用于检测是否此进程以管理员身份运行。 /// </summary> /// <returns> /// 如果此进程的权限已被提升,返回TRUE,反之则返回FALSE。 /// </returns> /// <exception cref="System.ComponentModel.Win32Exception"> /// 如果任何原生的Windows API函数出错,此函数会抛出一个包含最后错误代码的Win32Exception。 /// </exception> /// <remarks> /// TOKEN_INFORMATION_CLASS提供了TokenElevationType以便对当前进程的提升 /// 类型(TokenElevationTypeDefault / TokenElevationTypeLimited / /// TokenElevationTypeFull)进行检测。 它和TokenElevation的不同之处在于:当UAC /// 关闭时,即使当前进程已经被提升(完整性级别 == 高),权限提升类型总是返回 /// TokenElevationTypeDefault。换而言之,以此来确认当前线程的提升类型是不安全的。 /// 相对的,我们应该使用TokenElevation。 /// </remarks> internal bool IsProcessElevated() { bool fIsElevated = false; SafeTokenHandle hToken = null; int cbTokenElevation = 0; IntPtr pTokenElevation = IntPtr.Zero; try { // 使用TOKEN_QUERY打开进程主访问令牌 if (!NativeMethod.OpenProcessToken(Process.GetCurrentProcess().Handle, NativeMethod.TOKEN_QUERY, out hToken)) { throw new Win32Exception(); } // 为提升信息分配内存 cbTokenElevation = Marshal.SizeOf(typeof(TOKEN_ELEVATION)); pTokenElevation = Marshal.AllocHGlobal(cbTokenElevation); if (pTokenElevation == IntPtr.Zero) { throw new Win32Exception(); } // 获取令牌提升信息 if (!NativeMethod.GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenElevation, pTokenElevation, cbTokenElevation, out cbTokenElevation)) { // 当进程运行于Windows Vista之前的系统中,GetTokenInformation返回 // FALSE和错误码ERROR_INVALID_PARAMETER。这是由于这些操作系统不支 // 持TokenElevation。 throw new Win32Exception(); } // 转换TOKEN_ELEVATION结构(从原生到.Net) TOKEN_ELEVATION elevation = (TOKEN_ELEVATION)Marshal.PtrToStructure( pTokenElevation, typeof(TOKEN_ELEVATION)); // 如果令牌权限已经被提升,TOKEN_ELEVATION.TokenIsElevated是一个非0值 // 反之则为0 fIsElevated = (elevation.TokenIsElevated != 0); } finally { // 集中清理所有已分配的内存资源 if (hToken != null) { hToken.Close(); hToken = null; } if (pTokenElevation != IntPtr.Zero) { Marshal.FreeHGlobal(pTokenElevation); pTokenElevation = IntPtr.Zero; cbTokenElevation = 0; } } return(fIsElevated); }