/// <summary> /// Query a variable buffer from the object. /// </summary> /// <typeparam name="T">The type of structure to return.</typeparam> /// <param name="info_class">The information class to query.</param> /// <param name="default_value">A default value for the query.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The result of the query.</returns> /// <exception cref="NtException">Thrown on error.</exception> public virtual NtResult <SafeStructureInOutBuffer <T> > QueryBuffer <T>(Q info_class, T default_value, bool throw_on_error) where T : new() { NtStatus status; int return_length; // First try base size before trying to reallocate. using (var buffer = default_value.ToBuffer()) { status = QueryInformation(info_class, buffer, out return_length); if (status.IsSuccess()) { return(status.CreateResult(false, () => buffer.Detach())); } } if (!IsInvalidBufferStatus(status)) { return(status.CreateResultFromError <SafeStructureInOutBuffer <T> >(throw_on_error)); } // If the function returned a length then trust it. if (return_length > 0 && GetTrustReturnLength(info_class)) { using (var buffer = new SafeStructureInOutBuffer <T>(default_value, return_length, false)) { return(QueryInformation(info_class, buffer, out return_length).CreateResult(throw_on_error, () => buffer.Detach())); } } // Function length can't be trusted, we'll need to brute force it. return_length = GetSmallestPower2(Marshal.SizeOf(typeof(T))); int max_length = GetMaximumBruteForceLength(info_class); while (return_length < max_length) { using (var buffer = new SafeStructureInOutBuffer <T>(default_value, return_length, false)) { status = QueryInformation(info_class, buffer, out int dummy_length); if (status.IsSuccess()) { return(status.CreateResult(throw_on_error, () => buffer.Detach())); } else if (!IsInvalidBufferStatus(status)) { return(status.CreateResultFromError <SafeStructureInOutBuffer <T> >(throw_on_error)); } return_length *= 2; } } return(NtStatus.STATUS_BUFFER_TOO_SMALL.CreateResultFromError <SafeStructureInOutBuffer <T> >(throw_on_error)); }
private NtResult <SafeHGlobalBuffer> CreateAbsoluteSecurityDescriptor(bool throw_on_error) { byte[] dacl = Dacl?.ToByteArray(); byte[] sacl = Sacl?.ToByteArray(); byte[] owner = Owner?.Sid.ToArray(); byte[] group = Group?.Sid.ToArray(); int total_size = GetLength(dacl) + GetLength(sacl) + GetLength(owner) + GetLength(group); using (var sd_buffer = new SafeStructureInOutBuffer <SecurityDescriptorStructure>(total_size, true)) { NtStatus status = NtRtl.RtlCreateSecurityDescriptor(sd_buffer, Revision); if (!status.IsSuccess()) { return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error)); } SecurityDescriptorControl control = Control & SecurityDescriptorControl.ValidControlSetMask; status = NtRtl.RtlSetControlSecurityDescriptor(sd_buffer, control, control); if (!status.IsSuccess()) { return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error)); } int current_ofs = 0; if (Dacl != null) { IntPtr ptr = UpdateBuffer(sd_buffer, Dacl.NullAcl ? null : dacl, ref current_ofs); status = NtRtl.RtlSetDaclSecurityDescriptor(sd_buffer, true, ptr, Dacl.Defaulted); if (!status.IsSuccess()) { return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error)); } } if (Sacl != null) { IntPtr ptr = UpdateBuffer(sd_buffer, Sacl.NullAcl ? null : sacl, ref current_ofs); status = NtRtl.RtlSetSaclSecurityDescriptor(sd_buffer, true, ptr, Sacl.Defaulted); if (!status.IsSuccess()) { return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error)); } } if (Owner != null) { IntPtr ptr = UpdateBuffer(sd_buffer, owner, ref current_ofs); status = NtRtl.RtlSetOwnerSecurityDescriptor(sd_buffer, ptr, Owner.Defaulted); if (!status.IsSuccess()) { return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error)); } } if (Group != null) { IntPtr ptr = UpdateBuffer(sd_buffer, group, ref current_ofs); status = NtRtl.RtlSetGroupSecurityDescriptor(sd_buffer, ptr, Group.Defaulted); if (!status.IsSuccess()) { return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error)); } } return(status.CreateResult <SafeHGlobalBuffer>(throw_on_error, () => sd_buffer.Detach())); } }