コード例 #1
0
        /// <summary>
        ///     Performs a user impersonation based on a logon token.
        /// </summary>
        /// <param name="token"> The logon token. </param>
        /// <param name="loadUserProfile"> Specifies whether the users profile is to be loaded. </param>
        /// <param name="func"> The code to run under the impersonated user. </param>
        /// <returns>
        ///     The return value from <paramref name="func" />.
        /// </returns>
        /// <exception cref="ArgumentNullException"> <paramref name="func" /> is null. </exception>
        /// <exception cref="ArgumentException"> <paramref name="token" /> is zero. </exception>
        /// <exception cref="SecurityException"> The current user does not have sufficient permissions. </exception>
        /// <exception cref="Win32Exception">
        ///     The current user does not have sufficient permissions or the impersonation could not
        ///     be completed.
        /// </exception>
        public static Task <TResult> RunImpersonatedAsync <TResult> (IntPtr token, bool loadUserProfile,
                                                                     ImpersonatedFuncAsync <TResult> func)
        {
            if (func == null)
            {
                throw new ArgumentNullException(nameof(func));
            }

            if (token == IntPtr.Zero)
            {
                throw new ArgumentException("The token is zero.", nameof(token));
            }

            Task <TResult> result = WindowsIdentity.RunImpersonatedAsync(new SafeAccessTokenHandle(token), async() =>
            {
                WindowsIdentity identity   = null;
                WindowsUserProfile profile = null;

                try
                {
                    identity = new WindowsIdentity(token);

                    if (loadUserProfile)
                    {
                        USERPROFILE profileInfo = new USERPROFILE();
                        profileInfo.dwSize      = Marshal.SizeOf(profileInfo);
                        profileInfo.lpUserName  = identity.Name;
                        profileInfo.dwFlags     = 1;

                        bool loadSuccess = WindowsUser.LoadUserProfile(token, ref profileInfo);

                        if (!loadSuccess)
                        {
                            int errorCode       = WindowsApi.GetLastErrorCode();
                            string errorMessage = WindowsApi.GetErrorMessage(errorCode);
                            throw new Win32Exception(errorCode, errorMessage);
                        }

                        profile = new WindowsUserProfile(profileInfo);
                    }

                    return(await func(token, identity, profile));
                }
                finally
                {
                    if (profile != null)
                    {
                        WindowsUser.UnloadUserProfile(token, profile.NativeUserProfile.hProfile);
                    }

                    if (identity != null)
                    {
                        identity.Dispose();
                    }
                }
            });

            return(result);
        }