/// <summary>
		///   Checks whether the primary access token of the process belongs to a user account that is a member of the local Administrator group, even if it currently is not elevated.
		/// </summary>
		/// <returns>
		///   True if the primary access token of the process belongs to a user account that is a member of the Administrators group; false otherwise.
		/// </returns>
		public static bool IsUserInAdminGroup()
		{
			// Default token's received aren't impersonation tokens, we are looking for an impersonation token.
			bool isImpersonationToken = false;

			// Open the access token of the current process.
			SafeTokenHandle processToken;
			if ( !AdvApi32.OpenProcessToken( Process.GetCurrentProcess().Handle, (uint)(TokenAccessLevels.Query | TokenAccessLevels.Duplicate), out processToken ) )
			{
				MarshalHelper.ThrowLastWin32ErrorException();
			}

			// Starting from Vista linked tokens are supported which need to be checked.
			if ( EnvironmentHelper.VistaOrHigher )
			{
				// Determine token type: limited, elevated, or default.
				int marshalSize = sizeof( AdvApi32.TokenElevationType );
				var elevationTypeHandle = SafeUnmanagedMemoryHandle.FromNewlyAllocatedMemory( marshalSize );
				if ( !AdvApi32.GetTokenInformation( processToken, AdvApi32.TokenInformationClass.TokenElevationType, elevationTypeHandle.DangerousGetHandle(), marshalSize, out marshalSize ) )
				{
					MarshalHelper.ThrowLastWin32ErrorException();
				}
				var tokenType = (AdvApi32.TokenElevationType)Marshal.ReadInt32( elevationTypeHandle.DangerousGetHandle() );

				// If limited, get the linked elevated token for further check.
				if ( tokenType == AdvApi32.TokenElevationType.TokenElevationTypeLimited )
				{
					// Get the linked token.
					marshalSize = IntPtr.Size;
					var linkedTokenHandle = SafeUnmanagedMemoryHandle.FromNewlyAllocatedMemory( marshalSize );
					if ( !AdvApi32.GetTokenInformation( processToken, AdvApi32.TokenInformationClass.TokenLinkedToken, linkedTokenHandle.DangerousGetHandle(), marshalSize, out marshalSize ) )
					{
						MarshalHelper.ThrowLastWin32ErrorException();
					}
					processToken = new SafeTokenHandle( Marshal.ReadIntPtr( linkedTokenHandle.DangerousGetHandle() ) );
					isImpersonationToken = true; // Linked tokens are already impersonation tokens.
				}
			}

			// We need an impersonation token in order to check whether it contains admin SID.
			if ( !isImpersonationToken )
			{
				SafeTokenHandle impersonatedToken;
				if ( !AdvApi32.DuplicateToken( processToken, AdvApi32.SecurityImpersonationLevel.SecurityIdentification, out impersonatedToken ) )
				{
					MarshalHelper.ThrowLastWin32ErrorException();
				}
				processToken = impersonatedToken;
			}

			// Check if the token to be checked contains admin SID.
			var identity= new WindowsIdentity( processToken.DangerousGetHandle() );
			var principal = new WindowsPrincipal( identity );
			return principal.IsInRole( WindowsBuiltInRole.Administrator );
		}
		public extern static bool DuplicateToken( SafeTokenHandle existingTokenHandle, SecurityImpersonationLevel impersonationLevel, out SafeTokenHandle duplicateTokenHandle );
		public static extern bool GetTokenInformation( SafeTokenHandle tokenHandle, TokenInformationClass tokenInformationClass, IntPtr tokenInformation, int tokenInformationLength, out int returnLength );
		public static extern bool OpenProcessToken( IntPtr processHandle, UInt32 desiredAccess, out SafeTokenHandle tokenHandle );
		public static extern int SHSetKnownFolderPath( ref Guid folderId, KnownFolderRetrievalFlags flags, SafeTokenHandle accessToken, string path );
 public extern static bool DuplicateToken(SafeTokenHandle existingTokenHandle, SecurityImpersonationLevel impersonationLevel, out SafeTokenHandle duplicateTokenHandle);
 public static extern bool GetTokenInformation(SafeTokenHandle tokenHandle, TokenInformationClass tokenInformationClass, IntPtr tokenInformation, int tokenInformationLength, out int returnLength);
 public static extern bool OpenProcessToken(IntPtr processHandle, UInt32 desiredAccess, out SafeTokenHandle tokenHandle);