/// <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);
        }
Exemple #2
0
        /// <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);
        }