Beispiel #1
0
        /// <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));
        }
Beispiel #2
0
        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()));
            }
        }