/// <summary> /// Perform an Access Check. /// </summary> /// <param name="sd">The security descriptor for the check.</param> /// <param name="optional_sd">Optional list of security descriptors to merge.</param> /// <param name="desired_access">The desired access.</param> /// <param name="principal">Optional Principal SID.</param> /// <param name="object_types">Optional list of object types.</param> /// <param name="type">NT Type for access checking.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The list of access check results.</returns> /// <remarks>The list of object types is restricted to 256 entries for remote access checks.</remarks> public NtResult <AuthZAccessCheckResult[]> AccessCheck(SecurityDescriptor sd, IEnumerable <SecurityDescriptor> optional_sd, AccessMask desired_access, Sid principal, IEnumerable <ObjectTypeEntry> object_types, NtType type, bool throw_on_error) { if (sd is null) { throw new ArgumentNullException(nameof(sd)); } if (type is null) { throw new ArgumentNullException(nameof(type)); } using (var list = new DisposableList()) { AUTHZ_ACCESS_REQUEST request = new AUTHZ_ACCESS_REQUEST(); request.DesiredAccess = desired_access; if (principal != null) { request.PrincipalSelfSid = list.AddResource(principal.ToSafeBuffer()).DangerousGetHandle(); } int result_count = 1; var object_list = NtSecurity.ConvertObjectTypes(object_types, list); if (object_list?.Length > 0) { result_count = object_list.Length; request.ObjectTypeList = list.AddResource(object_list.ToBuffer()).DangerousGetHandle(); request.ObjectTypeListLength = object_list.Length; } var sd_buffer = list.AddResource(sd.ToSafeBuffer()); int optional_sd_count = optional_sd?.Count() ?? 0; IntPtr[] optional_sd_buffers = null; if (optional_sd_count > 0) { optional_sd_buffers = optional_sd.Select(s => list.AddResource(s.ToSafeBuffer()).DangerousGetHandle()).ToArray(); } AUTHZ_ACCESS_REPLY reply = new AUTHZ_ACCESS_REPLY(); reply.ResultListLength = result_count; var error_buffer = list.AddResource(new int[result_count].ToBuffer()); reply.Error = error_buffer.DangerousGetHandle(); var access_buffer = list.AddResource(new AccessMask[result_count].ToBuffer()); reply.GrantedAccessMask = access_buffer.DangerousGetHandle(); var audit_buffer = list.AddResource(new int[result_count].ToBuffer()); reply.SaclEvaluationResults = audit_buffer.DangerousGetHandle(); return(SecurityNativeMethods.AuthzAccessCheck(AuthZAccessCheckFlags.None, _handle, ref request, IntPtr.Zero, sd_buffer, optional_sd_buffers, optional_sd_count, ref reply, IntPtr.Zero).CreateWin32Result(throw_on_error, () => CreateResult(result_count, error_buffer, access_buffer, object_types?.ToArray(), type))); } }